By Syed Rizvi – Angular Architect with 20 Years of IT Experience
Optimization in Angular means improving the performance, loading time, and responsiveness of your application — both for user experience (UX) and system efficiency.
It involves minimizing bundle size, reducing change detection cycles, optimizing API calls, and improving rendering performance.
Common Angular Optimization Areas
| Area | Goal | Typical Techniques |
|---|---|---|
| Bundle Size | Reduce JS size, faster load | Lazy loading, route-based code splitting, tree shaking |
| Change Detection | Prevent unnecessary DOM checks | OnPush strategy, trackBy, Signals |
| Rendering | Avoid re-rendering heavy components | Virtual scrolling, pagination, caching |
| Network | Reduce API latency & calls | Debounce user input, caching with interceptors |
| Build Time | Smaller & faster builds | Ahead-of-Time (AOT) compilation, build optimizer |
| Images / Assets | Lighter media | Lazy loading images, compression (WebP) |
Real-Life Optimization Examples
1. Lazy Loading Feature Modules
Before:
All modules load on startup — large bundle = slow initial load.
After:
Use loadChildren to load modules only when needed.
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'reports', loadChildren: () => import('./reports/reports.module').then(m => m.ReportsModule) }
];
Real-world impact:
In one enterprise Angular app (~8MB bundle), lazy loading reduced initial load time from 9s → 2.5s on slow networks.
2. Change Detection Optimization (OnPush)
Default: Angular checks all components after every event.
Optimization: Use ChangeDetectionStrategy.OnPush to re-render only when inputs change.
@Component({
selector: 'app-user-card',
templateUrl: './user-card.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserCardComponent {
@Input() user!: User;
}
Real-world impact:
In a dashboard showing 500+ cards, CPU load dropped 40% after applying OnPush with immutable data.
3. Signals (Angular 16+) for Fine-Grained Reactivity
Instead of triggering whole component trees, signals update only reactive dependencies.
import { signal } from '@angular/core';
export class CartComponent {
count = signal(0);
add() { this.count.set(this.count() + 1); }
}
Impact: 30–40% faster updates for dynamic dashboards (Angular 16+).
4. Optimize API Calls with Interceptors
Use an HTTP interceptor to cache or debounce repeated API requests.
@Injectable()
export class CacheInterceptor implements HttpInterceptor {
private cache = new Map<string, HttpResponse<any>>();
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.cache.has(req.url)) {
return of(this.cache.get(req.url)!);
}
return next.handle(req).pipe(
tap(event => {
if (event instanceof HttpResponse) {
this.cache.set(req.url, event);
}
})
);
}
}
Impact: API hits reduced by 50% for auto-refreshing data grids.
5. Pagination / Virtual Scrolling for Large Lists
Instead of rendering 10,000 items, use Angular CDK’s virtual scroll.
<cdk-virtual-scroll-viewport itemSize="50" class="viewport">
<div *cdkVirtualFor="let item of items">{{ item.name }}</div>
</cdk-virtual-scroll-viewport>
Impact: Memory usage dropped from 300MB → 40MB for large tables.
6. AOT & Build Optimizer
In angular.json:
"configurations": {
"production": {
"aot": true,
"buildOptimizer": true,
"optimization": true
}
}
Impact: Smaller JS bundles (~30–50% reduction) and faster runtime.
Interview-Ready Summary Answer
“Angular optimization is about making the application faster and more efficient — by reducing bundle size, limiting change detection, and improving rendering. In one of my projects, I optimized an Angular 14 dashboard by applying lazy loading, OnPush strategy, and caching interceptors — which improved load time from 8 seconds to under 3 seconds and reduced API hits by 50%.”
