LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 4118 min read

Performance Optimization

Practical techniques for keeping an Angular app fast — OnPush, lazy loading, trackBy, and avoiding common change detection pitfalls.

OnPush Everywhere You Can

As covered in the change detection lesson, setting changeDetection: ChangeDetectionStrategy.OnPush on presentational components — fed entirely by @Input()/inputs — narrows how much of the tree Angular re-checks on every event, often the single biggest classic-Angular performance win available.

Lazy Load Everything Non-Critical

As covered in the lazy loading lesson, loadComponent and loadChildren keep your initial bundle small, deferring rarely-visited feature areas until they're actually needed.

track in @for / trackBy in *ngFor

A correct track expression (modern @for) or trackBy function (classic *ngFor) lets Angular reuse existing DOM nodes across a list update instead of destroying and recreating everything — critical for large or frequently-updated lists.

@for (product of products; track product.id) {
<app-product-card [product]="product" />
}

Virtual Scrolling for Long Lists

Angular CDK's ScrollingModule provides <cdk-virtual-scroll-viewport>, rendering only the items currently visible in the viewport and recycling DOM nodes as the user scrolls — essential for lists with hundreds or thousands of items.

<cdk-virtual-scroll-viewport itemSize="50" class="viewport">
<app-product-card *cdkVirtualFor="let product of products" [product]="product" />
</cdk-virtual-scroll-viewport>

Prefer Signals for Fine-Grained Updates

As covered in the signals lessons, components built around signal(), computed(), and input() update only the specific bindings that actually changed, sidestepping the broader Zone.js recheck model entirely for that data.

A Performance Checklist

  • Use OnPush for presentational components fed entirely by inputs.
  • Lazy-load feature areas and rarely-visited routes.
  • Always provide a correct track/trackBy for list rendering.
  • Virtualize genuinely long lists (hundreds+ of items).
  • Prefer signals over plain properties for values driving frequent UI updates.
  • Unsubscribe from long-lived Observable subscriptions in ngOnDestroy.

FAQs

Angular DevTools' profiler for component-level change detection insight, and Lighthouse in Chrome DevTools for overall page performance metrics.

Not automatically for classic property-based code — the benefit comes from actually migrating state to signal()/computed(), which then lets Angular update more precisely.

Summary

OnPush, lazy loading, correct list tracking, and signals together cover the vast majority of real-world Angular performance needs. Next, you'll look at server-side rendering with Angular Universal.

Next Lesson →

Server-Side Rendering with Angular Universal