Angular 20 brings a wide range of updates: improvements to reactivity, SSR, support for zoneless architecture, template syntax enhancements, better tooling, and more.
Below is a categorized breakdown of all the changes:
At the end, I’ll share some of my personal highlights 👇
effect
, linkedSignal
, toSignal
are now stable APIs.incremental hydration
and route-level rendering mode config
have also
reached stable status.unhandledRejection
, uncaughtException
).resource
API to trigger async operations from signals.streamingResource
for working with WebSocket streams.httpResource
wraps HttpClient
in a reactive, signal-based API.llms.txt
file to help LLMs generate up-to-date Angular code.@defer
blocks, hydration state, and zones.trackFn
calls, ??
misuse, missing
imports, etc.createComponent
Enhancementsbindings
, directives
, and two-way binding
.**
(exponentiation), in
operator, and untagged template
literals.host
object.typeCheckHostBindings
flag in tsconfig.json
.Component
, Service
, Pipe
are now optional.*ngIf
, *ngFor
, and *ngSwitch
are now deprecated. New control flow syntax
@if
, @for
, @switch
is preferred. Migration command:
ng generate @angular/core:control-flow
I've often run into issues with Zone.js
—from odd side effects during state
updates to unpredictable behavior due to monkey-patching. On the server, it's
even worse, causing memory leaks in Node.js and hard-to-trace crashes.
Now, you can bootstrap your app without Zone.js using:
bootstrapApplication(AppComponent, {
providers: [
provideZonelessChangeDetection(),
provideBrowserGlobalErrorListeners()
]
});
Just make sure to remove the zone.js
polyfill from angular.json
. This
greatly simplifies debugging and SSR stability.
createComponent
APICreating dynamic components used to be verbose. Now, it’s all declarative:
createComponent(MyDialog, {
bindings: [
inputBinding('canClose', signal(true)),
outputBinding('onClose', (result) => console.log(result)),
twoWayBinding('title', signal('Dialog Title'))
],
directives: [FocusTrap]
});
This is a major improvement, especially for UI library authors. It unlocks powerful use cases. It is like host directives, but in runtime and dynamic.
@HostBinding
and @HostListener
were convenient, but the main problem for me
was that they don't work with signals and Observables. Now you can express this
clearly in the host
object with full editor support:
@Component({
host: {
'[class.active]': 'isActive()',
'(click)': 'handleClick()',
}
})
And now with typeCheckHostBindings
enabled:
{
"angularCompilerOptions": {
"typeCheckHostBindings": true
}
}
You get type safety and better DX.
*ngIf
, *ngFor
, *ngSwitch
This was long overdue. The new control flow syntax is simpler, closer to
JavaScript, and removes the need to import CommonModule
.
Migration is easy:
ng generate @angular/core:control-flow
From this:
<div *ngIf="user">{{ user.name }}</div>
To this:
@if (user) {
<div>{{ user.name }}</div>
}
Cleaner, more readable, fewer surprises.
This was a solid release. Of course, as developers, we always wish new features were stabilized faster and shipped more frequently — but that doesn't make us any less excited for the next major in six months or the RFCs in between.
Meanwhile, minor releases might still bring exciting updates. And yes, we’re looking at you, signal-based forms ✌️
🟢 Course updates on ng.guide will go live as soon as Nx 20 adds support for Angular 20.
🎁 Pre-order now — "Angular UI Kit"
We’re launching our first interactive course on ng.guide, where you'll build a production-grade UI library using real-world Angular practices.
💸 Early-bird price: $99 (was $125) — available only before launch.
Reserve your access now and get hands-on with how Angular works at scale.