DEV Community

Soumaya Erradi
Soumaya Erradi

Posted on

Angular Change Detection with Zoneless

Change detection is at the heart of every Angular application. It ensures that the application's user interface (UI) stays in sync with its data model. Traditionally, Angular has relied on a mechanism called zones, powered by the zone.js library, to make this happen. But with Angular’s latest version, a new zoneless change detection feature is introduced, marking a significant shift in how developers can optimize their applications.

In this article, we will explore:

  1. How change detection works in Angular.
  2. Problems caused by zones.
  3. The introduction of zoneless mode and how to use it.
  4. Handling complex situations with zoneless change detection.
  5. Why signals and zoneless mode are a powerful combination.
  6. The benefits and revolutionary impact of this feature.

Understanding Change Detection in Angular

Change detection is the process Angular uses to make sure the application's UI is always updated with the latest data. This happens automatically whenever something changes in your application, whether it’s a user action, an HTTP request or a timer event.

In Angular, every component has its own change detection mechanism, which checks if the values in the component's template have changed and updates the DOM accordingly.

Zones and their role

Angular has traditionally used zone.js to patch asynchronous operations such as:

  • HTTP requests.
  • Event listeners (e.g., button clicks).
  • Timers like setTimeout or setInterval.

When any of these operations are completed, zone.js automatically triggers Angular's change detection mechanism, ensuring the UI stays in sync. This makes development easier, as developers don’t need to worry about manually updating the UI.


The problems with Zones

While zone.js simplifies development, it introduces some challenges:

  1. Performance overhead: By patching all asynchronous operations, zone.js adds unnecessary overhead, especially in large or high-performance applications.
  2. Debugging complexity: Debugging issues becomes harder because zone.js modifies how asynchronous operations work under the hood.
  3. Compatibility issues: Some modern browser APIs and third-party libraries don’t work well with zone.js.
  4. Unnecessary change detection: Angular’s change detection runs even when the application’s state hasn’t changed, leading to wasted resources.

The Zoneless revolution in Angular

With the release of Angular v19, the framework introduced an experimental zoneless mode to address these problems. Zoneless mode allows Angular to run without zone.js, giving developers more control over when and how change detection happens.

What does Zoneless mode do?

In zoneless mode:

  • Angular no longer automatically tracks asynchronous operations.
  • Developers must manually trigger change detection when data changes.
  • The application becomes leaner and faster since there’s no overhead from zone.js.

How to use Zoneless mode

Zoneless mode might feel like a significant shift, but breaking it into clear steps ensures a smooth transition. Here's a detailed guide:

Step 1: Disable Zone.js

To disable zones, start by removing the zone.js library from your application.

  1. Update polyfills.ts: Remove or comment out the import for zone.js:
   // polyfills.ts
   // Remove or comment out the following line:
   // import 'zone.js';
Enter fullscreen mode Exit fullscreen mode
  1. Remove from Dependencies: Check your package.json and remove zone.js from the dependencies section:
   {
     "dependencies": {
       "zone.js": "^0.12.0" // Remove this dependency
     }
   }
Enter fullscreen mode Exit fullscreen mode
  1. Uninstall the Library: Run the following command to uninstall zone.js completely:
   npm uninstall zone.js
Enter fullscreen mode Exit fullscreen mode

Step 2: Bootstrap without Zone.js

Angular provides a dedicated function, provideExperimentalZonelessChangeDetection(), to enable zoneless mode in your application. This function ensures that Angular initializes without zone.js and uses the experimental zoneless change detection.

Here’s how to configure it in your main.ts file:

import { bootstrapApplication } from '@angular/platform-browser';
import { provideExperimentalZonelessChangeDetection } from '@angular/core';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, {
  providers: [
    provideExperimentalZonelessChangeDetection(), // Enable zoneless change detection
  ],
}).catch(err => console.error(err));
Enter fullscreen mode Exit fullscreen mode

Step 3: Manually trigger change detection

Once zones are disabled, Angular will no longer automatically run change detection. You need to trigger it manually when state changes occur.

Using ChangeDetectorRef

The ChangeDetectorRef service allows you to invoke change detection at the component level. Additionally, the markForCheck() method is useful in scenarios where you want Angular to schedule change detection for components with OnPush change detection strategy:

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

@Component({
  selector: 'app-root',
  template: `
    <div>
      <h1>Counter: {{ counter }}</h1>
      <button (click)="incrementCounter()">Increment</button>
    </div>
  `,
})
export class AppComponent {
  counter = 0;

  constructor(private cdr: ChangeDetectorRef) {}

  incrementCounter() {
    this.counter++;
    this.cdr.markForCheck(); // Mark the component for checking during the next change detection cycle
  }
}
Enter fullscreen mode Exit fullscreen mode

Using ApplicationRef

For global state changes, you can use ApplicationRef.tick() to trigger change detection across the entire application:

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

@Component({
  selector: 'app-global-tick',
  template: `
    <button (click)="updateState()">Update State</button>
    <p>{{ message }}</p>
  `,
})
export class GlobalTickComponent {
  message = 'Initial State';

  constructor(private appRef: ApplicationRef) {}

  updateState() {
    this.message = 'Updated State';
    this.appRef.tick(); // Trigger change detection globally
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Optimize with Signals

Angular signals, introduced with Angular's new reactivity model, are an excellent companion to zoneless mode. Signals track state changes efficiently and automatically update the UI without manual calls to change detection.

Here’s a simple example using signals:

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

@Component({
  selector: 'app-signal-demo',
  template: `
    <h1>Signal Counter: {{ count() }}</h1>
    <button (click)="increment()">Increment</button>
  `,
})
export class SignalDemoComponent {
  count = signal(0);

  increment() {
    this.count.set(this.count() + 1);
  }
}
Enter fullscreen mode Exit fullscreen mode

In this setup, the signal automatically tracks changes, and the UI updates without the need for explicit detectChanges calls.


Handling complex situations

Scenario: multiple data streams

When working with multiple asynchronous streams (e.g., using RxJS), AsyncPipe remains a reliable solution in zoneless mode. It simplifies data binding and eliminates the need for manual change detection:

import { Component } from '@angular/core';
import { interval } from 'rxjs';

@Component({
  selector: 'app-multi-stream',
  template: `<p>Stream Value: {{ value$ | async }}</p>`
})
export class MultiStreamComponent {
  value$ = interval(1000); // Emits a value every second
}
Enter fullscreen mode Exit fullscreen mode

Why Zoneless mode is revolutionary

  1. Performance gains: Applications become faster and more efficient by eliminating zone-related overhead.
  2. Developer control: Zoneless mode lets you decide when to update the UI, leading to better-optimized apps.
  3. Compatibility: Works seamlessly with modern APIs and third-party libraries.
  4. Enhanced reactivity: Combined with signals, zoneless mode simplifies state management and improves app responsiveness.

Conclusion

The introduction of zoneless change detection in Angular is a game-changer. It empowers developers to build faster, more efficient applications while giving them greater control over how and when updates happen. Coupled with Angular signals, zoneless mode unlocks new possibilities for optimizing performance and simplifying state management.

As Angular continues to evolve, features like this reinforce its position as one of the most versatile and powerful frameworks for modern web development!

Top comments (0)