Angular 52: Performance — OnPush Change Detection & track
easy⏱ 5 mincourseangular
OnPush + signals: precise updates instead of full sweeps
With ChangeDetectionStrategy.OnPush, Angular stops walking into a component during the default check and only re-renders it when something it actually depends on changes — a new input() reference, a DOM event inside it, or (since Angular tracks signal reads in templates) a signal it reads being updated. That's exactly what happens here: updating products is the only thing that can cause a re-render.
@Component({
selector: 'app-product-list',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `...`,
})
export class ProductListComponent {}
track is mandatory in @for, and it's what makes list updates fast
Every @for block requires a track expression — usually a stable, unique id like product.id. Angular uses it to match old and new list items across renders, so it only patches the DOM nodes that actually moved, added or were removed, instead of tearing down and rebuilding the whole list.
@for (product of products(); track product.id) {
<li>{{ product.name }}</li>
} @empty {
<li>No products yet.</li>
}
@empty renders when the tracked list has nothing to show
The optional @empty block inside @for renders automatically when the iterable is empty — no separate @if (products().length === 0) needed alongside it.