DEV Community

Nikhil Sai
Nikhil Sai

Posted on

Optimizing the Performance of an Angular Application

"Before learning about performance optimization, first we will learn some ways through which we can analyze the performance of any web application"

1. Using Chrome DevTools:

This is a set of web developer tools built into the Google Chrome browser. You can use the Performance tab to record and analyze the runtime performance of your Angular application, such as CPU usage, memory consumption, rendering time, etc.

  • Open your Angular application in Chrome browser
  • Press Ctrl+Shift+I (Windows) or Cmd+Option+I (Mac) to open DevTools
  • Click on the Performance tab
  • Click on the Record button or press Ctrl+E (Windows) or Cmd+E (Mac) to start recording
  • Perform some actions on your Angular application
  • Click on the Stop button or press Ctrl+E (Windows) or Cmd+E (Mac) to stop recording
  • Analyze the performance results in the DevTools panel

2. Using WebPageTest:

This is a web-based tool that performs website speed tests from multiple locations around the globe using real browsers and at real consumer connection speeds.

  • Go to https://www.webpagetest.org/
  • Enter the URL of your Angular application in the Test Location field
  • Choose a test location and a browser from the dropdown menus
  • Click on the Start Test button
  • Wait for the test to finish and view the performance results on the web page

3. Using Angular CLI (Specific to Angular application):

  • Open a terminal and navigate to your Angular project folder
  • ng build --stats-json // This builds your Angular application and generates a stats.json file in the dist folder
  • ng serve --stats-json // This serves your Angular application and generates a stats.json file in the dist folder

"Now let's see how we can optimize the Angular application"

10 ways to optimize your Angular Application

1. Enable production mode: This mode performs many significant optimizations not available in a development build, such as ahead-of-time compilation, minification, and tree-shaking.

// Enabling production mode
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
  enableProdMode(); // This enables production mode
}
platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.error(err));
Enter fullscreen mode Exit fullscreen mode

2. Use AOT compilation: This reduces your app payload by removing the Angular compiler from the deployment bundle and producing only the compiled templates. You can use the --aot flag with the ng build or ng serve commands.

ng build --prod --aot=true
Enter fullscreen mode Exit fullscreen mode

3. Use build optimizer: This removes Angular specific decorators, constructor parameters and makes it easier for code minifiers to remove unused code. You can use the --buildOptimizer flag with the ng build command.

ng build --prod --buildOptimizer=true
Enter fullscreen mode Exit fullscreen mode

4. Avoid function calls and getters in views: These can trigger unnecessary change detection cycles and affect performance. Instead, use properties or pure pipes to display data in views.

5. Use pure pipes: These are only re-evaluated when the input changes, unlike impure pipes that are re-evaluated on every change detection cycle. You can create a pure pipe by setting the pure property to true in the @Pipe decorator.

@Pipe({
  name: 'square',
  pure: true // This tells Angular to only recompute the pipe output when the input changes
})
export class SquarePipe implements PipeTransform {
  transform(value: number): number {
    return value * value;
  }
}
Enter fullscreen mode Exit fullscreen mode

6.Use lazy loading modules: This allows you to load modules on demand, rather than loading them all at once. This reduces the initial loading time and improves performance. You can use the Angular CLI to generate lazy loading modules with the --route flag.

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
const routes: Routes = [
  {
    path: 'customers',
    loadChildren: () => import('./customers/customers.module').then(m => m.CustomersModule) // This loads the customers module on demand
  },
  {
    path: 'orders',
    loadChildren: () => import('./orders/orders.module').then(m => m.OrdersModule) // This loads the orders module on demand
  },
  {
    path: '',
    redirectTo: '',
    pathMatch: 'full'
  }
];
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
Enter fullscreen mode Exit fullscreen mode

7. Use code splitting: This is a technique that splits your code into smaller chunks that can be loaded asynchronously. This reduces the size of your main bundle and improves performance. You can use tools such as Webpack or Rollup to implement code splitting.

8. Use OnPush change detection strategy: This tells Angular to only check for changes when the input properties change or an event is triggered. This reduces the number of change detection cycles and improves performance. You can set the changeDetection property to ChangeDetectionStrategy.OnPush in the @Component decorator.

@Component({
  selector: 'app-my-component',
  templateUrl: './my-component.component.html',
  styleUrls: ['./my-component.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush // This tells Angular to only check for changes when the input properties change or an event is triggered
})
export class MyComponentComponent implements OnInit {
  @Input() data: any; // This is an input property that can change from outside
  constructor() { }
  ngOnInit(): void {
  }
}
Enter fullscreen mode Exit fullscreen mode

9. Use async pipe: This is a built-in pipe that subscribes to an observable or promise and returns the latest value. It also handles unsubscribing automatically, which prevents memory leaks. You can use the async pipe in your template with the syntax

{{ observableOrPromise | async }}.
Enter fullscreen mode Exit fullscreen mode

10. Use trackBy function on ngFor: This is a function that returns a unique identifier for each item in an array. It helps Angular to track changes and reuse existing elements, rather than creating new ones. This improves performance and reduces memory usage. You can use the trackBy function in your template with the syntax *ngFor="let item of items; trackBy: trackById".

@Component({
  selector: 'app-my-list',
  template: `
    <ul>
      <li *ngFor="let item of items; trackBy: trackById">{{item.name}}</li>
    </ul>
  `
})
export class MyListComponent {
  items = [
    {id: 1, name: 'Alice'},
    {id: 2, name: 'Bob'},
    {id: 3, name: 'Charlie'}
  ];
  // This function returns the unique identifier of each item
  trackById(index: number, item: any) {
    return item.id;
  }
}
Enter fullscreen mode Exit fullscreen mode

Above mentioned are some of the ways through which we can optimize our Angular Application. Apart from these you can also use techniques like pagination, cache, storing data in local, session storage and avoiding the unnecessary API calls etc...

Thank's for your time, see you soon :)

Top comments (0)