Angular — What’s new in V20 ?
We will try exploring few of new features from Angular v20
Zoneless Change Detection ( Experimental )
Going zoneless in Angular means running your application without relying on NgZone for change detection. This is a major shift introduced alongside Angular's Signals-based reactivity model, especially as of Angular v17+ and Angular 20.
What is ngZone ?
Angular traditionally uses Zone.js to patch all async APIs (e.g., setTimeout, XHR, Promise, etc.) to automatically trigger change detection after every async task.
Problems with NgZone:
- Performance overhead: It runs change detection on every async operation, even if the DOM doesn’t need updating.
- Debugging complexity: Hard to trace what triggered change detection.
- Inefficient for reactive UIs: With reactive primitives like signals, Angular can track only what’s needed —
NgZonebecomes redundant.
What is Zoneless?
Zoneless Angular apps opt out of NgZone, and instead use fine-grained change detection via:
- Signals
- Component-level effects
- Manual
detectChanges()(when needed)
With experimental zoneless feature, Angular has signals and event-based reactivity to manage change detection paving for zoneless architecture.
// Remove zone.js
import { provideZoneChangeDetection } from '@angular/core';
bootstrapApplication(AppComponent, {
providers: [
provideZoneChangeDetection('noop') // disables Zone.js
]
});
Benefits:
⚡ Better performance — Eliminates global change detection for every async task.
📦 Smaller bundle size — No need to include Zone.js.
🎯 Fine-grained reactivity — With signals, only affected components re-render.
🧪 More predictable behavior — You know exactly when and why change detection runs.
🔍 Easier debugging — Less magic from patched async APIs.
🔧 Better suited for micro-frontends — Avoids global side effects caused by Zone.js.
Signal-Based Reactivity (Stable)
Signals are a new primitive for managing reactive state, providing a predictable and efficient data flow.
Most signal APIs (including linkedSignal, effect, and resource streaming APIs) are now stable and fully supported, making this the recommended way to build reactive apps in Angular 20.
They provide fine-grained, performant, and predictable change detection — a huge step forward from traditional @Input, @Output, and RxJS
import { signal, computed } from '@angular/core';
const count = signal(0);
const double = computed(() => count() * 2);
count.set(5);
console.log(double()); // 10// computed() – creates a derived signal
readonly doubleCount = computed(() => this.count() * 2);
// effect() – runs side effects when signals change
effect(() => {
console.log(`New count: ${this.count()}`);
});Benefits:-
⚡ Fast — Only updates parts of the DOM that depend on the changed signal
🔍 Trackable — Easy to trace which state change caused a UI update
♻️ Reusable — You can share signals across components/services
🧘 Zoneless compatible — Works perfectly without NgZone
🧠 Synchronous — Simpler mental model than RxJS streams
Hydration Enhancements
Hydration is the process where Angular takes the HTML rendered on the server and “activates” it on the client, attaching event listeners and making the app interactive — without re-rendering the DOM.
Without hydration:
- Angular re-renders everything from scratch.
- The user sees the same HTML twice (wasted work).
- DOM is replaced, potentially causing flicker or layout shift.
With hydration:
- Angular reuses the server-rendered DOM.
- Adds interactivity without re-rendering.
- Faster, smoother user experience.
Angular has evolved its hydration strategy, making it more reliable, faster, and customizable.
Get Naveen’s stories in your inbox
Join Medium for free to get updates from this writer.
Angular 17:
- Introduced partial hydration for basic components.
- Started using hydration markers in HTML to detect rehydration needs.
Angular 19:
- Supported deferred blocks (
@defer) and control flow (@if,@for) with hydration.
Angular 20:
- Improved granularity and customization with:
- Better support for
@defer+ hydration. - Fixes for edge cases like form inputs, bindings, and dynamic content.
- Configurable hydration strategies.
// Hydration is automatically enabled when using Angular Universal with SSR.
import { provideClientHydration } from '@angular/platform-browser';
bootstrapApplication(AppComponent, {
providers: [
provideClientHydration({
deferBlock: true // Only hydrate @defer blocks when they appear
})
]
});// Example
// Angular ensures the placeholder is rendered on server,
// and the profile component hydrates only when userLoaded is true
@defer (when userLoaded; loading) {
<app-user-profile />
}
@placeholder {
<p>Loading...</p>
}Stabilized control flow
Angular has traditionally used structural directives like *ngIf, *ngFor, *ngSwitch.
Angular compiles these control blocks into efficient low-level instructions — even more optimized than structural directives like *ngIf and *ngFor.
They also support hydration in Angular Universal and deferred loading via @defer.
// New way
@if (condition) {
<p>It’s true!</p>
} @else {
<p>It’s false.</p>
}
@for (item of items; track item.id) {
<div>{{ item.name }}</div>
}
@switch (type) {
@case ('cat') { }
@case ('dog') { }
@default { ❓ }
}// destructuring and index
@for ((user, i) of users) {
<div>{{ i + 1 }}. {{ user.name }}</div>
}Angular 17:
- New syntax introduced:
-@if / @else
-@for (item of items)
-@switch / @case / @default
- Initially available only in standalone components
- Required explicit import from
@angular/common - Was in developer preview — not recommended for production
Angular 19:
- Control flow now worked better with Signals, @defer blocks, Zoneless apps
Angular 20:
- Control flow syntax is now stable and fully supported
- Supports nested blocks, trackBy, and destructuring
- Fully integrated with hydration, defer, and signals
- No preview, works in both standalone and NgModule-based components
Chrome DevTools Integration
Resources:-
https://blog.ninja-squad.com/2025/05/28/what-is-new-angular-20.0/









