Quick steps you can use to improve Angular change detection performance

Daniel Kreider
Daniel Kreider
Published on March 6th at 7:00am
  • Angular Performance
  • Angular Change Detection

Here's how to find the change detection bottle-necks in your application.

And discover ways to make your Angular application zing.

Did you know that Angular change detection has limits?

And if you're not wise, it'll get sluggish and sour and make you look like a bad developer.

So how about we pop the hood on Angular's engine?

And learn how to detect and fix change detection issues?

How does Angular Change Detection work?

Angular uses a library widely known as Zone.js to detect DOM events. These DOM events are mouse clicks, keyboard press and so forth.

When Zone.js detects a DOM event, it checks the data bindings and updates the incorrect ones that way the data show to the user is always fresh.

And that is change detection in a nutshell. It might be a cool feature but it's got limits… and… if you abuse Angular change detection it'll get cranky.

So how do we dig up change detection performance issues?

Enable Angular's Debug Tools

Open the main.ts file (used to bootstrap your Angular application) and edit these lines of code...

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.error(err));

...to look like this.

platformBrowserDynamic().bootstrapModule(AppModule)
  .then(module => enableDebugTools(module.injector.get(ApplicationRef).components[0]))
  .catch(err => console.error(err));

Profiling Change Detection Time

Now that we've got the debug tools enabled, we can use them to discover how long change detection is taking.

We'll run our Angular application with ng serve --open.

As soon as it launches in your browser, open the console in Developer Tools and type the following command to measure how long the last change detection cycle lasted.

ng.profiler.timeChangeDetection()

For a very basic Angular application you can expect a change detection cycle of 0.01 - 0.05 milliseconds. And although opinions vary, I would recommend that you never let your change detection cycle go beyond 10ms.

So how do you fix bad change detection performance?

Let's say we have an Angular component that displays a list of 5,000 random numbers.

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-number-list',
  template: `
    <ul>
        <li *ngFor="let number of numbers">{{ number }}</li>
    </ul>
  `,
  styleUrls: ['./number-list.component.css']
})
export class NumberListComponent implements OnInit {

  numbers: number[] = [];

  constructor() { }

  ngOnInit(): void {
    this.generateNumbers();
  }

  generateNumbers(): void {
    for(let i = 0; i < 5000; i++) {
      let number = Math.random();
      this.numbers.push(number);
    }
  }
}

How well do you think it will perform?

Well, when I checked the change detection cycle it was taking at least 12 - 14ms. 😯

This is a simple example of a bad-performing component. Lists are a bad culprit for long change detection cycles and a good way to fix a long list is to use a virtual scrolling strategy. The Angular Material CDK has a great virtual scrolling package worth checking into.

Conclusion

And there you have it, my friend. You've learned how to quickly enable change detection debugging and find out how long Angular change detection is taking.

Questions or comments? Don't hesitate to contact me.

Angular Expert & Consultant