Guide pratique des nouvelles fonctionnalités Angular 20 : effect() amélioré, afterRenderEffect(), signal queries, amélioration des forms réactifs et nouveaux outils CLI.
Résumé des changements Angular 20
Angular 20 est la version de la maturité. Les APIs expérimentales des versions précédentes passent en stable, les outils sont affinés et la DX (Developer Experience) atteint un nouveau niveau de qualité.
Highlights Angular 20 :
- effect() stable : API finalisée, plus d'expérimental
- afterRenderEffect() stable : remplacement de afterViewInit pour les effets DOM
- Signal queries stables : viewChild(), contentChild(), viewChildren()
- Zoneless stable : provideZonelessChangeDetection() sans "Experimental"
- resource() et httpResource() stables
- HMR des templates : mise à jour HTML sans rechargement
- CLI 20 : build 40% plus rapide avec esbuild v2
effect() stable et amélioré
La fonction effect(), expérimentale depuis Angular 16, passe en stable dans Angular 20. Son comportement est également amélioré : les effets ne s'exécutent plus pendant l'injection si non nécessaire.
Avant (Angular 18-19) :
// Nécessitait allowSignalWrites pour modifier des signaux dans effect()
effect(() => {
const value = this.source();
this.derived.set(value * 2); // ⚠️ erreur sans option
}, { allowSignalWrites: true });
Après (Angular 20) :
// allowSignalWrites n'est plus nécessaire
effect(() => {
const value = this.source();
this.derived.set(value * 2); // ✅ fonctionne directement
});
// Cleanup intégré et stable
effect((onCleanup) => {
const sub = this.service.stream$.subscribe(v => this.data.set(v));
onCleanup(() => sub.unsubscribe());
});
afterRenderEffect() stable
afterRenderEffect() remplace avantageusement AfterViewInit et afterNextRender() pour les opérations DOM réactives. Il s'exécute après chaque rendu et se ré-exécute automatiquement quand ses dépendances de signaux changent.
import { afterRenderEffect, signal, ElementRef } from '@angular/core';
@Component({ ... })
export class ChartComponent {
data = signal<number[]>([]);
constructor(private el: ElementRef) {
// S'exécute après chaque rendu où data() change
afterRenderEffect(() => {
const canvas = this.el.nativeElement.querySelector('canvas');
this.renderChart(canvas, this.data());
});
}
}
afterNextRender() s'exécute une seule fois. afterRenderEffect() se ré-exécute à chaque changement des signaux qu'il lit.
Signal queries : viewChild et contentChild
Les signal queries remplacent les décorateurs @ViewChild, @ContentChild, @ViewChildren et @ContentChildren. Elles retournent des signaux et s'intègrent nativement avec computed() et effect().
Avant (Angular 18 et avant) :
@ViewChild('myInput') inputRef!: ElementRef;
@ContentChild(IconComponent) icon?: IconComponent;
@ViewChildren(ItemComponent) items!: QueryList<ItemComponent>;
Après (Angular 20 — signal queries stables) :
import { viewChild, contentChild, viewChildren } from '@angular/core';
@Component({ ... })
export class FormComponent {
// Signal : undefined si non trouvé
inputRef = viewChild<ElementRef>('myInput');
// Signal requis : erreur si absent
inputRequired = viewChild.required<ElementRef>('myInput');
// ContentChild signal
icon = contentChild(IconComponent);
// ViewChildren : Signal<ReadonlyArray<T>>
items = viewChildren(ItemComponent);
constructor() {
effect(() => {
const input = this.inputRequired();
input.nativeElement.focus(); // accès réactif
});
}
}
Zoneless change detection stable
Le mode zoneless, expérimental depuis Angular 18, devient stable dans Angular 20. La fonction change de nom.
Angular 18-19 (expérimental) :
import { provideExperimentalZonelessChangeDetection } from '@angular/core';
bootstrapApplication(AppComponent, {
providers: [provideExperimentalZonelessChangeDetection()]
});
Angular 20 (stable) :
import { provideZonelessChangeDetection } from '@angular/core';
bootstrapApplication(AppComponent, {
providers: [provideZonelessChangeDetection()]
});
// angular.json : supprimer zone.js des polyfills
// "polyfills": [] ← plus de "zone.js"
Améliorations CLI et build
Angular CLI 20 apporte des gains significatifs sur les temps de build.
- esbuild v2 : build de production 40% plus rapide
- HMR des templates : les modifications HTML sont appliquées sans rechargement (en plus des styles)
- ng build --stats : rapport détaillé du bundle (taille par chunk, tree-shaking)
- Schematic migrations automatiques : mise à jour des APIs dépréciées en une commande
# Migrer les ViewChild vers signal queries
ng generate @angular/core:signal-queries-migration
# Migrer effect() (supprime allowSignalWrites)
ng generate @angular/core:effect-migration
# Rapport de bundle
ng build --stats-json
npx webpack-bundle-analyzer dist/my-app/stats.json
Migration d'Angular 19 à 20
Migration sans breaking changes majeurs, entièrement automatisée.
1. Mettre à jour :
ng update @angular/cli@20 @angular/core@20
2. Renommer provideExperimentalZonelessChangeDetection :
# Le schematic le fait automatiquement
ng update @angular/core@20
3. Migrer les signal queries (optionnel) :
ng generate @angular/core:signal-queries-migration
Prérequis :
- TypeScript 5.7 ou supérieur
- Node.js 20.11+ ou 22.x
- Angular 19 requis avant de passer à 20
@ViewChild, @Output et Zone.js tant que vous ne les avez pas migrés.