Angular 21 marque une étape charnière dans l'évolution du framework de Google. Après plusieurs versions de préparation, les fonctionnalités majeures introduites depuis Angular 16 atteignent leur pleine maturité. Signals, la détection de changements sans Zone.js, et une expérience développeur radicalement améliorée sont au cœur de cette release.
1. L'API Signals — Pleinement stable
Introduite en preview dans Angular 16, l'API Signals est désormais 100% stable dans Angular 21. Elle remplace le modèle de détection de changements basé sur Zone.js par un système réactif fin-grained.
Signal inputs, outputs et queries
import { Component, input, output, model, signal } from '@angular/core';
@Component({
selector: 'app-counter',
standalone: true,
template: `
<button (click)="decrement()">-</button>
<span>{{ count() }}</span>
<button (click)="increment()">+</button>
`
})
export class CounterComponent {
// Signal input (remplace @Input)
initialValue = input<number>(0);
// Signal output (remplace @Output + EventEmitter)
changed = output<number>();
// Two-way binding avec model()
count = model(0);
increment() {
this.count.update(v => v + 1);
this.changed.emit(this.count());
}
decrement() { this.count.update(v => v - 1); }
}
computed() et effect()
import { signal, computed, effect } from '@angular/core';
const firstName = signal('Kriss');
const lastName = signal('Clotilde');
// Valeur dérivée recalculée automatiquement
const fullName = computed(() => `${firstName()} ${lastName()}`);
// Effet qui s'exécute à chaque changement
effect(() => {
console.log('Nom complet :', fullName());
});
firstName.set('Jean'); // → 'Jean Clotilde'
2. Zoneless — Détection de changements sans Zone.js
La détection de changements zoneless est maintenant stable et recommandée pour les nouvelles applications. Fini le monkey-patching de toutes les API asynchrones du navigateur par Zone.js.
import { provideExperimentalZonelessChangeDetection } from '@angular/core';
// En Angular 21, plus besoin du préfixe "Experimental"
import { provideZonelessChangeDetection } from '@angular/core';
export const appConfig: ApplicationConfig = {
providers: [
provideZonelessChangeDetection(),
provideRouter(routes),
]
};
En mode zoneless, la vue ne se met à jour que lorsqu'un Signal change, ou lorsque vous appelez manuellement ChangeDetectorRef.markForCheck(). Les performances sont nettement améliorées sur les grandes applications.
3. La syntaxe @let dans les templates
Angular 21 stabilise la déclaration de variables locales dans les templates avec @let, une longue demande de la communauté.
<!-- Avant Angular 17 : utilisation de ng-template -->
<ng-container *ngLet="user$ | async as user">
{{ user?.name }}
</ng-container>
<!-- Angular 21 — @let natif -->
@let user = userSignal();
@let fullName = user.firstName + ' ' + user.lastName;
<h1>Bonjour, {{ fullName }} !</h1>
@if (user.isAdmin) {
@let adminLabel = 'Administrateur';
<span class="badge">{{ adminLabel }}</span>
}
4. Resource API — Gestion async déclarative
La Resource API simplifie radicalement le chargement de données asynchrones. Elle remplace les patterns complexes à base de ngOnInit + Observable + gestion manuelle du loading/error.
import { resource, signal } from '@angular/core';
@Component({
template: `
@if (userResource.isLoading()) {
<p>Chargement...</p>
} @else if (userResource.error()) {
<p>Erreur : {{ userResource.error() }}</p>
} @else {
<p>{{ userResource.value()?.name }}</p>
}
`
})
export class UserComponent {
userId = signal(1);
// Recharge automatiquement quand userId change
userResource = resource({
request: () => ({ id: this.userId() }),
loader: ({ request }) =>
fetch(`/api/users/${request.id}`).then(r => r.json())
});
}
5. Hydratation incrémentale stable
L'hydratation incrémentale, annoncée en preview dans Angular 19, est désormais stable. Elle permet de n'hydrater les composants que lorsqu'ils entrent dans le viewport ou lors d'une interaction utilisateur.
<!-- Hydratation différée au survol -->
@defer (hydrate on hover) {
<app-heavy-chart [data]="chartData()" />
}
<!-- Hydratation au viewport -->
@defer (hydrate on viewport) {
<app-comments-section />
}
<!-- Toujours pré-rendu en SSR, hydraté à la demande -->
@defer (hydrate on interaction) {
<app-user-settings />
}
6. Récapitulatif des nouveautés Angular 21
Signals stable
signal(), computed(), effect(), input(), output(), model() — tout est stable et recommandé.
Zoneless stable
Plus de Zone.js. Détection de changements fine-grained, meilleures performances.
Resource API
Chargement de données asynchrones avec états loading/error intégrés.
@let en template
Déclaration de variables locales directement dans les templates HTML.
Hydratation incrémentale
Hydratation SSR conditionnelle par viewport, hover ou interaction.
HMR amélioré
Hot Module Replacement plus rapide avec support des Signals et styles à la volée.
7. Migration depuis Angular 17-20
La migration est facilitée par le schematic officiel. Les composants basés sur @Input() / @Output() continuent de fonctionner sans modification. La migration peut se faire progressivement, composant par composant.
# Mise à jour vers Angular 21
ng update @angular/core@21 @angular/cli@21
# Migration automatique vers signal inputs
ng generate @angular/core:signal-input-migration
# Migration vers signal queries
ng generate @angular/core:signal-queries-migration
Attention : Zone.js est toujours supporté mais entre progressivement en mode "maintenance". Il est recommandé de planifier la migration vers le mode zoneless pour les nouvelles fonctionnalités et optimisations futures.