Different optimization techniques for angular application with code examples

 Optimizing an Angular application is crucial for improving its performance, especially as applications grow in size and complexity. Optimization can involve improving the runtime performance, reducing the initial load time, optimizing memory usage, and improving responsiveness. Below are the key optimization techniques you can apply in an Angular application, explained in detail with code examples.

1. Lazy Loading

Lazy loading is the technique of loading Angular modules only when they are needed. This reduces the initial load time by loading less code upfront and splitting the application into smaller bundles.

How to Implement Lazy Loading:

  1. Define feature modules.
  2. Use loadChildren in the router configuration to load modules only when necessary.
Example:
// app-routing.module.ts import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) // Lazy loading the AdminModule }, ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
  • AdminModule will only be loaded when the user navigates to /admin.
  • This optimizes the initial load time by deferring the loading of unnecessary parts of the app.

2. Change Detection Strategy

Angular uses change detection to update the view when the model changes. By default, Angular uses ChangeDetectionStrategy.Default, which checks the entire component tree for changes.

You can optimize this by switching to ChangeDetectionStrategy.OnPush, which tells Angular to check the component only when its inputs change or when an event occurs inside the component.

How to Implement OnPush Change Detection:

import { Component, ChangeDetectionStrategy } from '@angular/core'; @Component({ selector: 'app-my-component', templateUrl: './my-component.component.html', styleUrls: ['./my-component.component.css'], changeDetection: ChangeDetectionStrategy.OnPush }) export class MyComponent { data: any; }
  • ChangeDetectionStrategy.OnPush helps in reducing unnecessary change detection checks and improves the performance of larger applications.

3. Track By with NgFor

Using trackBy in Angular’s *ngFor can significantly optimize performance when rendering lists, especially when the list is large. By default, Angular compares the entire DOM tree when it detects changes. trackBy tells Angular how to track each item in the list, reducing the number of DOM manipulations.

How to Implement TrackBy:

<ul> <li *ngFor="let item of items; trackBy: trackById">{{ item.name }}</li> </ul>

export class MyComponent { items = [{ id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }, { id: 3, name: 'Item 3' }]; trackById(index: number, item: any): number { return item.id; // Track items by their unique 'id' } }
  • trackBy optimizes the list rendering by allowing Angular to efficiently track items based on a unique identifier (such as id), instead of re-rendering the entire list when only a few items change.

4. Tree Shaking

Tree shaking is the process of removing unused code during the build process. Modern bundlers like Webpack (used in Angular) can eliminate code that is not being used.

How to Enable Tree Shaking:

Tree shaking is enabled by default in Angular when building in production mode. You need to make sure that you use ES modules and avoid dynamic imports or side-effect-heavy code.

ng build --prod
  • When building with --prod, Angular optimizes the final bundle by removing dead code that is not used in the application.

5. Ahead-of-Time (AOT) Compilation

AOT compilation pre-compiles Angular templates and components during the build process. This reduces the amount of code that needs to be compiled in the browser, speeding up the initial load time.

How to Enable AOT:

ng build --prod
  • By default, Angular enables AOT when building in production mode.
  • With AOT, templates and components are compiled before the browser loads them, improving the performance by reducing the JavaScript payload.

6. Optimize Image Loading

Images can be a significant factor in slow page load times. To optimize images, you can use techniques like lazy loading, serving images in modern formats (e.g., WebP), and responsive images.

How to Implement Lazy Loading for Images:

<img [defaultImage]="defaultImage" [lazyLoad]="imageSrc" [alt]="imageAlt" />
  • Use ngx-lazy-load-images or Angular’s native loading="lazy" to load images only when they enter the viewport.
<img src="large-image.jpg" loading="lazy" alt="Lazy Loaded Image" />
  • This will load images only when they are about to be visible, reducing the initial page load time.

7. Service Workers and Caching

Service workers enable caching of resources on the client side, reducing the load on the server and enabling offline capabilities.

How to Implement Service Worker:

ng add @angular/pwa
  • This command automatically adds service worker support to your Angular app.
  • Service workers cache assets (HTML, CSS, JS) and API responses, improving performance by reducing reliance on the network and enabling offline usage.

8. Optimize Angular HTTP Requests

When making HTTP requests, always handle caching and error handling properly to avoid unnecessary network requests. Use Angular’s HttpInterceptor to cache responses.

Example of HTTP Caching with Interceptors:

import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; import { Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; @Injectable() export class CacheInterceptor implements HttpInterceptor { private cache = new Map<string, HttpEvent<any>>(); intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { if (this.cache.has(req.url)) { return Observable.of(this.cache.get(req.url)); // Return cached response } else { return next.handle(req).pipe( tap(event => { if (event instanceof HttpResponse) { this.cache.set(req.url, event); // Cache the response } }) ); } } }
  • Interceptors help cache API responses, so repeated requests to the same API endpoint can be served from the cache instead of making network calls.

9. Web Workers for Heavy Computations

Web Workers allow you to run JavaScript in a separate thread, improving performance for CPU-intensive tasks like image processing, large calculations, etc.

How to Implement Web Workers:

ng generate web-worker worker
  • This command generates a web worker file. You can offload heavy tasks to the web worker to avoid blocking the main thread.
// In your component or service if (typeof Worker !== 'undefined') { const worker = new Worker('./worker.worker', { type: 'module' }); worker.postMessage(data); worker.onmessage = ({ data }) => { console.log('Received data from worker', data); }; }
  • By using web workers, Angular can process tasks like image manipulation or sorting large datasets in the background without freezing the UI.

10. Preloading Strategy

When lazy loading modules, you can pre-load certain modules in the background to ensure they are ready when the user navigates to them.

How to Implement Preloading:

import { PreloadAllModules } from '@angular/router'; @NgModule({ imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })], }) export class AppRoutingModule {}
  • This strategy will preload all lazy-loaded modules after the app is loaded, so when the user navigates to different parts of the app, they load instantly.

Conclusion

By implementing these optimization techniques, you can significantly improve the performance and user experience of your Angular application. Each of the methods above targets different areas, such as reducing the initial load time, optimizing rendering, and handling large datasets efficiently. Applying these techniques will help ensure that your Angular app scales efficiently and performs well under heavy usage.

Comments

Popular posts from this blog

PrimeNG tutorial with examples using frequently used classes

Docker and Kubernetes Tutorials and QnA

Building strong foundational knowledge in frontend development topics