Angular 20 : nouvelles fonctionnalités et APIs pratiques

🏷️ Front-end 📅 12/04/2026 18:00:00 👤 Mezgani said
Angular Angular 20 Nouveautes Signals Cli
Angular 20 : nouvelles fonctionnalités et APIs pratiques

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é.

À retenir : Angular 20 = stabilisation complète des signaux + zoneless stable + CLI optimisé. C'est la version idéale pour migrer des projets en production.

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());
    });
  }
}
Différence avec afterNextRender() : 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"
À retenir : Les nouveaux projets Angular 20 n'incluent plus Zone.js par défaut. Le bundle initial est allégé de ~150 KB et le démarrage est plus rapide.

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
Migration progressive : Toutes les nouvelles APIs sont rétrocompatibles. Vous pouvez continuer à utiliser @ViewChild, @Output et Zone.js tant que vous ne les avez pas migrés.