visit
How to optimize an Angular app? First, we need to consider how we understand optimization as such. Optimization helps achieve better app performance and easier code maintenance. Optimization is not a checklist or a to-do-list, and there is no universal way to optimize your app.
Optimization is a process, and it should start at the same time as the app development. It’s really hard to optimize the application that already exists (though it’s still possible of course), so we should take care of it during the whole project.
Here's a list of the best tips to help keep your code in line with good practices and make your Angular application faster. Enjoy and optimize!Fortunately, with Angular, we don’t have to remember to add Webpack scripts to minify the code. All we have to do is make a bundle using
ng build --prod
command. It’s just good to know when and how it happens.@Component({
...
changeDetection: ChangeDetectionStrategy.OnPush
})
Change detector for a component with OnPush Strategy will be triggered only when a value in @Input() has been changed, an event has been emitted by a template, an event has been triggered by Observable in this component or
this.changeDetector.markForCheck()
has been called.class foo {
private _bar: boolean = false;
get bar(): boolean {
return this._bar;
}
}
get
used in the view is nothing more than a function call. A better idea is to use pure pipes which will always return the same output, no matter how many times they will receive the same input. If the Change Detector reaches this view and pure in the pipe is set to true (default), the Change Detector will not check if that value has been changed because it knows that it will return exactly the same value.<div>Time: {{ time | async }}</div>
With async pipe, there's no need to bother about unsubscribing. What’s more, Change Detector will check if the value was changed only when Observable had changed itself.
let sub1: Subscription;
let sub2: Subscription;
ngOnInit() {
this.sub1 = this.service.Subject1.subscribe(() => {});
this.sub2 = this.service.Subject2.subscribe(() => {});
}
ngOnDestroy() {
if (this.sub1) {
this.sub1.unsubscribe();
}
if (this.sub2) {
this.sub2.unsubscribe();
}
}
let subs: Subscription[] = [];
ngOnInit() {
this.subs.push(this.service.Subject1.subscribe(() => {}));
this.subs.push(this.service.Subject2.subscribe(() => {}));
}
ngOnDestroy() {
subs.forEach(sub => sub.unsubscribe());
}
private subscriptions = new Subscription();
ngOnInit() {
this.subscriptions.add(this.service.Subject1.subscribe(() => {}));
this.subscriptions.add(this.service.Subject2.subscribe(() => {}));
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
ngUnsubscribe = new Subject();
ngOnInit() {
this.service.Subject1.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(() => {});
this.service.Subject2.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(() => {});
}
ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
*ngFor="let item of items; trackBy: trackByFn"
trackBy is a parameter that accepts a function that should return a unique value of each item of the list. Without using trackBy function, *ngFor will re-render each and every element of the list every time that list changes (each element will be removed from DOM and rendered once again). With trackBy function, only the values that have been changed will be re-rendered or deleted.
import { concat } from 'lodash'
concat([1], 2, [3], [[4]])
[1].concat(2, [3], [[4]])
import { chunk } from “lodash”
import * from “lodash”
Properties will be loaded only if the component is used in the rendered page, so it means better performance for the application. For you, as a front-end developer, it means that the SCSS is scoped and simplified, so you will be probably more productive during development.
When using
ng build --prod
to build, the Angular CLI will compile and bundle all components into the application.When using
ng build --prod --build-optimizer
to build, all of the unused components will be omitted.--build-optimizer
activates tree shaking (a term commonly used for dead-code elimination in JavaScript context) on Webpack.Unfortunately, this can cause some bugs, so be really careful while doing that and rather than excluding dead code, try including living code.
[Source: ]
If if the property covers all of these criteria omit the brackets and uselabel="Save"
[label]=”’Save’”
This way the Change Detector will not check it while running in the component.
10. Dependencies between components
The next thing to consider are dependencies between components in the application. Are all of them really necessary? Do you want and need them all? Try to check it by generating and analyzing dependencies graph (for example NGD: Angular Dependencies Graph).It can be also helpful when you start working on an already existing project and want to have an overview of the architecture of the application.
A good practice is to use a CSS animation to make a global loader for the application - then, even if the JavaScript of the application doesn’t load properly, the user can see a nice, animated loader.
const routes: Routes = [
{ path: 'account',
loadChildren: () => import('./account/account.module')
.then(m => m.AccountModule) },
{ path: admin,
loadChildren: () => import('./admin/admin.module')
.then(m => m.AdminModule) }
];
What's more, you can try lazy load for a bigger amount of images or longer content - load it on scroll.