How do you optimize the performance of an Angular application?
Learn to optimize Angular performance with OnPush change detection, lazy loading, trackBy, virtual scrolling, and profiling for faster loads and smoother UIs.
Expected Interview Answer
You optimize an Angular app by reducing unnecessary change detection, shrinking and lazy-loading the bundle, and deferring or virtualizing expensive work so the browser does less on each interaction.
Key levers include the OnPush change detection strategy with immutable data, lazy-loaded routes and code splitting, trackBy in *ngFor, standalone components with tree-shaking, and pure pipes instead of method calls in templates. Beyond that, use the async pipe to manage subscriptions, virtual scrolling for long lists, server-side rendering or hydration for faster first paint, and production builds with AOT and minification. Profiling with Angular DevTools and Lighthouse guides where to focus.
- Faster initial load and time to interactive
- Fewer wasted change detection cycles
- Smaller download through lazy loading and tree-shaking
- Smoother scrolling and rendering of large lists
- Lower memory use and fewer leaked subscriptions
- Better Core Web Vitals and user experience
AI Mentor Explanation
Optimizing Angular is like managing a bowling attack: you don't send every bowler every over. OnPush is picking the right bowler only when the situation changes, lazy loading is keeping fielders in the pavilion until needed, and trackBy is not re-setting the entire field placement just because one new batter walked in.
Step-by-Step Explanation
Step 1
Profile first
Use Angular DevTools and Lighthouse to find slow change detection, large bundles, and layout shifts.
Step 2
Tune change detection
Adopt OnPush with immutable data and the async pipe so components re-render only when inputs change.
Step 3
Split the bundle
Lazy-load feature routes and use standalone components so tree-shaking removes unused code.
Step 4
Optimize lists
Add trackBy to *ngFor and use CDK virtual scrolling for long or infinite lists.
Step 5
Fix template hotspots
Replace method calls in templates with pure pipes or memoized values to avoid recomputation.
Step 6
Improve load and paint
Enable production AOT builds, SSR or hydration, and preload critical assets for faster first paint.
What Interviewer Expects
- Knowledge of OnPush and change detection cost
- Lazy loading and code-splitting strategy
- trackBy and virtual scrolling for large lists
- Avoiding method calls in templates
- Use of profiling tools to guide optimization
- Awareness of SSR/hydration and production builds
Common Mistakes
- Optimizing blindly without profiling first
- Calling functions directly in templates
- Forgetting trackBy in large *ngFor lists
- Leaking subscriptions instead of using async pipe
- Eagerly loading every feature module upfront
- Mutating objects while using OnPush, breaking updates
Best Answer (HR Friendly)
“You make an Angular app faster by doing less unnecessary work: only updating the parts of the screen that changed, loading features when they're needed instead of all at once, and efficiently handling long lists. You measure with tools first, then fix the biggest bottlenecks.”
Code Example
@Component({
selector: 'app-user-list',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div *ngFor="let user of users$ | async; trackBy: trackById">
{{ user.name }}
</div>
`,
})
export class UserListComponent {
users$ = this.store.users$;
trackById(index: number, user: { id: number }) {
return user.id;
}
}Follow-up Questions
- How does OnPush change detection actually work?
- Why are method calls in templates a performance problem?
- What does trackBy do in an *ngFor loop?
- How does lazy loading reduce initial bundle size?
- When would you use CDK virtual scrolling?
- How does SSR or hydration improve perceived performance?
MCQ Practice
1. Which change detection strategy reduces unnecessary re-renders?
OnPush re-renders a component only when its input references change or an event fires, cutting wasted checks.
2. What is the purpose of trackBy in *ngFor?
trackBy gives each item a stable identity so Angular reuses existing DOM nodes instead of re-creating them.
3. Which technique reduces the initial bundle size?
Lazy loading defers loading feature code until its route is visited, shrinking the initial download.
Flash Cards
What does OnPush do? — Re-renders a component only when input references change or an event occurs.
Why avoid method calls in templates? — They run on every change detection cycle; use pure pipes or memoized values instead.
What is trackBy for? — Gives list items stable identity so Angular reuses DOM nodes in *ngFor.
How does lazy loading help? — Loads feature code only when its route is visited, reducing initial bundle size.
Tool to profile change detection? — Angular DevTools, plus Lighthouse for load performance.
Continue Learning
Related Interview Questions
What is lazy loading in Angular and how does it improve performance?
medium
What is change detection in Angular and how does the OnPush strategy optimize it?
hard
What is Zone.js and what role does it play in Angular change detection?
medium
What are Angular pipes and how do pure and impure pipes differ?
medium