Angular Performance Optimization: Best Techniques to Improve Application Performance
Learn Angular performance optimization techniques to build faster applications. Explore lazy loading, OnPush, Signals, trackBy, caching, code splitting, SSR and more.

Angular Performance Optimization: Best Techniques to Improve Application Performance
Performance is an important part of any Angular application. An application may have all the required features, but if pages take too long to load or the UI becomes slow while using it, users may leave the application.
As an Angular application grows, it can contain many components, API calls, images, third-party libraries, and business logic. If these are not handled properly, they can affect the application's loading time and runtime performance.
Angular provides several features that help developers build fast and efficient applications. In this article, we will look at some practical Angular performance optimization techniques that can be used in real projects.
Why is Angular Performance Optimization Important?
A slow application can affect both user experience and business results.
Some common performance problems are:
- Slow initial page loading
- Large JavaScript bundles
- Unnecessary API calls
- Too many component updates
- Slow rendering of large lists
- Large images
- Unnecessary calculations
- Loading features that users may never open
Performance optimization helps reduce these problems and makes the application more responsive.
1. Use Lazy Loading
Lazy loading is one of the most useful techniques for improving the initial loading time of an Angular application.
Instead of loading all application features when the application starts, you can load a feature only when the user visits that part of the application.
For example, an application may have:
Dashboard
Users
Reports
Settings
AdminThere is no need to load all of these features when the user only wants to open the Dashboard. With lazy loading, the required feature is loaded when the user navigates to it.
{
path: 'reports',
loadComponent: () =>
import('./reports/reports.component')
.then(m => m.ReportsComponent)
}This reduces the amount of JavaScript that needs to be downloaded during the initial page load.
2. Use OnPush Change Detection
Angular's change detection checks components to determine whether the UI needs to be updated. For components that do not need frequent checks, onPush can reduce unnecessary change detection work.
@Component({
selector: 'app-user',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './user.component.html'
})
export class UserComponent {}With onPush, Angular can skip certain checks when the component's inputs and other relevant conditions have not changed.
This can be especially useful in applications with many components.
3. Use Angular Signals
Signals provide a simple way to manage reactive state in Angular.
Instead of causing broad updates for every state change, Signals allow Angular to track which parts of the application depend on a particular value.
count = signal(0);
increment() {
this.count.update(value => value + 1);
}In the template:
<p>{{ count() }}</p>Signals are particularly useful for local component state and can work well with Angular's modern change detection approach.
4. Use trackBy for Large Lists
Rendering a large list can become expensive if Angular has to recreate many DOM elements when the data changes.
For example:
<div *ngFor="let user of users; trackBy: trackByUserId">
{{ user.name }}
</div>The trackBy function can identify each item using a unique value.
trackByUserId(index: number, user: User) {
return user.id;
}This helps Angular reuse existing DOM elements instead of recreating them unnecessarily when the list changes.
For modern Angular versions, the @for syntax can also use a tracking expression:
@for (user of users; track user.id) {
<div>{{ user.name }}</div>
}5. Avoid Unnecessary API Calls
Repeated API calls can affect both application performance and backend performance.
For example, calling the same API every time a component is initialized may not be necessary if the data has not changed. Caching can help in such cases.
RxJS provides operators such as shareReply() that can be useful when multiple subscribers need the same API result.
users$ = this.http.get<User[]>('/api/users').pipe(
shareReplay(1)
);The exact caching strategy should depend on how frequently the data changes.
6. Use Async Pipe
The async pipe is useful when working with Observables in Angular templates. Instead of manually subscribing and unsubscribing:
users: User[] = [];
ngOnInit() {
this.userService.getUsers()
.subscribe(data => {
this.users = data;
});
}You can expose the Observable:
users$ = this.userService.getUsers();And use it in the template:
<div *ngFor="let user of users$ | async">
{{ user.name }}
</div>The async pipe manages the subscription lifecycle and can make the component code simpler.
7. Optimize Images
Images can have a major impact on page loading performance. Using a very large image when the application only displays a small version wastes bandwidth.
Some useful practices include:
- Compress images
- Use modern image formats such as WebP or AVIF
- Use appropriate image dimensions
- Lazy load images that are below the initial viewport
- Avoid unnecessarily large background images
Angular also provides image optimization features through NgOptimizedImage.
For example:
<img ngSrc="assets/images/banner.webp"
width="1200" height="600"
priority alt="Angular
performance optimization">For important images that appear immediately on the page, proper prioritization can help the browser load them earlier.
8. Reduce Bundle Size
A large JavaScript bundle can increase the time required to download, parse, and execute the application. Avoid importing an entire library when you only need a small part of it.
For example, check the libraries used by the application and remove packages that are no longer required.
You should also use production builds because Angular can apply build optimizations such as minification and bundling.
ng build --configuration productionRegularly checking bundle sizes can help identify packages that are increasing the application's size.
9. Use Code Splitting
Code splitting breaks application code into smaller chunks. Lazy-loaded routes naturally help with this because Angular can create separate chunks for features that are loaded later.
The idea is simple:
Initial Load
↓
Core Application
↓
User opens Reports
↓
Reports chunk loadsThis means users do not have to download every feature before they can start using the application.
10. Avoid Heavy Work in Templates
Avoid calling expensive functions directly from templates.
For example:
<p>{{ calculateTotal(items) }}</p>If calculateTotal() performs a large calculation, it may be executed repeatedly during change detection.
Instead, calculate the value when the data changes and expose the result to the template.
For reactive applications, computed Signals can also be useful:
total = computed(() =>
this.items().reduce((sum, item) => sum + item.price, 0)
);Then:
<p>{{ total() }}</p>11. Use Server-Side Rendering When Needed
For applications where initial page rendering and search engine visibility are important, Angular Server-Side Rendering (SSR) can be useful.
With SSR, the server can generate the initial HTML before sending it to the browser. This can improve the experience of seeing the first page and can be useful for content-heavy applications.
However, SSR is not a replacement for other performance techniques. Large bundles, slow APIs, and unoptimized images can still affect the overall application.
12. Avoid Unnecessary Third-Party Libraries
Third-party packages can make development easier, but adding too many libraries can increase bundle size and application complexity.
Before adding a package, consider:
- Do I really need it?
- Is Angular already providing this functionality?
- How large is the package?
- Is it actively maintained?
- Can the same functionality be implemented with a small amount of code?
Removing unnecessary dependencies can make an application smaller and easier to maintain.
How to Find Performance Problems?
Performance optimization should not be based only on assumptions. Use browser and Angular tools to find the actual problem.
You can check:
- Network requests
- JavaScript bundle sizes
- API response times
- Rendering performance
- Memory usage
- Core Web Vitals
- Large images
- Long-running JavaScript tasks
For example, Chrome DevTools can help identify slow network requests and large resources. Angular DevTools can also help inspect components and understand application behavior.
Best Practices Checklist
Before deploying an Angular application, check the following:
- Use lazy loading for large features
- Use onPush where appropriate
- Use Signals for suitable reactive state
- Track large lists properly
- Avoid unnecessary API requests
- Cache data when appropriate
- Optimize images
- Keep JavaScript bundles small
- Remove unused dependencies
- Avoid expensive template expressions
- Use production builds
- Consider SSR when the application benefits from it
- Measure performance instead of guessing
Conclusion
Angular performance optimization is not about using one particular technique. It is usually a combination of several small improvements.
Lazy loading can reduce the initial bundle; OnPush and Signals can help reduce unnecessary UI work; proper list tracking can improve rendering; caching can reduce repeated API calls, and image optimization can reduce network usage.
The most important thing is to first identify where the application is slow and then apply the technique that addresses that specific problem.
A well-optimized Angular application should not only load quickly but should also remain responsive as the number of components, users, API calls, and features increases.
Frequently Asked Questions
How can I improve the initial loading time of an Angular application?
Use lazy loading, reduce the initial JavaScript bundle, optimize images, remove unnecessary dependencies, and use production builds. SSR can also help applications where fast initial rendering is important.
Does OnPush always make an Angular application faster?
Not necessarily. onPush can reduce unnecessary change detection work, but the actual improvement depends on the application's component structure and how data is updated.
How do I find what is making my Angular application slow?
Use Chrome DevTools and Angular DevTools to inspect network requests, bundle sizes, rendering activity, API response times, and long-running JavaScript tasks. Measuring the actual bottleneck is better than applying optimizations without checking the problem first.
Version History 2 updates
- Sep 7, 2026
Updated: title, description, content, categories, tags, featuredImage, images, status, faqs, seriesName, seriesOrder, wordCount, readingTimeMinutes, slug, rejectionReason
- Sep 6, 2026
Updated: title, description, content, categories, tags, featuredImage, images, status, faqs, seriesName, seriesOrder, wordCount, readingTimeMinutes, slug, rejectionReason