Angular is a powerful framework for building complex web applications, but performance issues can arise if best practices are not followed. Optimizing an Angular app ensures smooth user experience, faster load times, and better scalability. In this article, we will explore the top 10 performance improvement techniques for Angular apps, complete with explanations and code snippets.
By default, Angular uses the Default
change detection strategy, which checks for changes across the entire component tree. Instead, use OnPush
to reduce unnecessary change detection cycles.
import { ChangeDetectionStrategy, Component, Input } from "@angular/core";
@Component({
selector: "app-optimized",
template: `<p>{{ data }}</p>`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class OptimizedComponent {
@Input() data!: string;
}
This tells Angular to check for changes only when the @Input()
reference changes, improving performance.
Loading all modules at once slows down the application. Implement lazy loading to load modules only when required.
const routes: Routes = [{ path: "feature", loadChildren: () => import("./feature/feature.module").then((m) => m.FeatureModule) }];
This ensures that the feature
module is loaded only when the user navigates to it.
Using trackBy
in *ngFor
prevents Angular from recreating DOM elements unnecessarily.
<li *ngFor="let item of items; trackBy: trackByFn">{{ item.name }}</li>
trackByFn(index: number, item: any): number {
return item.id;
}
This ensures that only modified elements are updated in the DOM, reducing re-renders.
Avoid calling functions inside templates as they are executed on every change detection cycle.
Instead of:
<p>{{ getFormattedDate() }}</p>
Use a pure pipe:
@Pipe({ name: "formatDate", pure: true })
export class FormatDatePipe implements PipeTransform {
transform(value: Date): string {
return new Intl.DateTimeFormat("en-US").format(value);
}
}
<p>{{ date | formatDate }}</p>
For large lists, use Angular’s cdk-virtual-scroll-viewport
to render only visible elements.
<cdk-virtual-scroll-viewport itemSize="50" class="viewport">
<div *cdkVirtualFor="let item of items">{{ item.name }}</div>
</cdk-virtual-scroll-viewport>
This drastically improves performance when dealing with long lists.
Move CPU-intensive operations to a Web Worker to prevent UI blocking.
Create a new worker:
const worker = new Worker(new URL("./app.worker", import.meta.url), { type: "module" });
worker.onmessage = ({ data }) => {
console.log(`Worker result: ${data}`);
};
worker.postMessage("start computation");
This allows expensive computations to run in the background.
Tree shaking removes unused code, reducing the bundle size. Ensure that you:
import { something } from 'package'
)import * as _ from 'lodash'
)Angular’s production build (ng build --prod
) automatically enables tree shaking.
AOT compilation precompiles Angular HTML and TypeScript during the build process, improving runtime performance.
Enable AOT in angular.json
:
"angularCompilerOptions": {
"enableIvy": true
}
And build with:
ng build --aot
Reduce unnecessary API calls using caching with shareReplay
.
import { HttpClient } from "@angular/common/http";
import { map, shareReplay } from "rxjs/operators";
this.data$ = this.http.get("/api/data").pipe(shareReplay(1));
This caches the response and avoids redundant network requests.
Compress images, use lazy loading, and serve assets efficiently:
Use .webp
instead of .png
or .jpg
Enable lazy loading for images:
<img src="image.webp" loading="lazy" alt="Optimized Image" />
Use a CDN to serve static assets faster
Performance optimization in Angular requires multiple strategies, from fine-tuning change detection to reducing bundle sizes. By implementing these techniques, your Angular application will load faster, perform better, and provide a seamless user experience.