Angular
Signaux et mode zoneless avec Angular 22 : ce qui change pour une application existante
Le mode zoneless supprime le déclenchement automatique des mises à jour. Concrètement, cela rend visibles les rendus inutiles et impose de revoir la façon dont l'état circule dans l'application.
Pendant des années, le déclenchement des mises à jour dans Angular reposait sur une règle simple : toute tâche asynchrone terminée provoquait une vérification de l'arbre de composants. Pratique, mais coûteuse : une requête HTTP, un minuteur ou un événement de socket relançaient une vérification qui n'avait souvent aucun effet visible.
Angular 22 rend le mode zoneless utilisable en production. Est-ce une bonne idée sur une application existante ? Oui, à condition de traiter la migration comme un travail d'architecture et non comme un changement de configuration.
Ce que le mode zoneless change réellement
Sans zone.js, Angular ne sait plus qu'une donnée a changé : il faut le lui dire. Les signaux remplissent ce rôle, mais uniquement à l'intérieur du système de signaux. Un objet modifié par mutation après un appel réseau classique ne déclenchera aucun rendu. Ce n'est pas un défaut : c'est précisément ce qui rend le comportement prévisible.
@Component({
selector: 'app-order-list',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class OrderListComponent {
private readonly ordersService = inject(OrdersService);
readonly filter = signal<OrderFilter>({ status: 'OPEN', page: 0 });
readonly orders = toSignal(
toObservable(this.filter).pipe(
switchMap(filter => this.ordersService.search(filter)),
),
{ initialValue: [] as Order[] },
);
readonly total = computed(() =>
this.orders().reduce((sum, order) => sum + order.amount, 0),
);
onStatusChange(status: OrderStatus): void {
this.filter.update(current => ({ ...current, status }));
}
}
Migrer par étapes plutôt que globalement
La migration que nous appliquons se déroule en quatre étapes, dans cet ordre précis, chaque étape restant livrable en production.
- Activer la détection de changements explicite sur les composants les plus sollicités.
- Convertir les états locaux en signaux, en commençant par les filtres et les compteurs.
- Remplacer les abonnements manuels par des signaux dérivés, en supprimant chaque appel explicite au marquage de vérification.
- Retirer zone.js du démarrage de l'application et surveiller les écrans les plus complexes.
Le piège des mises à jour venues de l'extérieur
Les bibliothèques tierces et certaines API du navigateur restent hors du système de signaux : gestionnaires d'événements de carte, lecteurs vidéo, websockets encapsulés. Chaque point d'entrée externe doit être converti explicitement en signal, faute de quoi l'écran se figera silencieusement. Recenser ces points avant de démarrer évite une phase de débogage longue et frustrante.
Le rendu serveur et le mode zoneless
Le rendu serveur bénéficie directement de cette évolution. Le serveur attend que l'application soit stable avant d'envoyer la page ; sans zone.js, cette stabilité dépend uniquement des signaux et des requêtes en cours, ce qui réduit les attentes inutiles. Côté back-end, la pagination et le filtrage doivent rester côté serveur pour tirer parti de ce gain.
@GetMapping("/orders")
Page<OrderResponse> search(@Valid OrderSearchCriteria criteria, Pageable pageable) {
return orderSearch.search(criteria, pageable).map(OrderResponse::from);
}
| Pratique | Avec zone.js | En mode zoneless |
|---|---|---|
| Mise à jour après un appel HTTP | Automatique | Explicite via un signal |
| Coût d'un événement sans effet visuel | Vérification complète de l'arbre | Aucune vérification |
| État partagé entre composants | Souvent un sujet par composant | Signal fourni par un service |
| Diagnostic d'un écran figé | Rare | Point d'entrée externe oublié |
Le mode zoneless ne rend pas une application rapide : il rend visible chaque mise à jour déclenchée pour rien.
Mesurer avant de généraliser
Nous mesurons trois indicateurs avant et après migration : le temps d'interaction sur les écrans de liste, le nombre de cycles de rendu sur un scénario répétable, et le temps de stabilisation du rendu serveur. Ces mesures déterminent s'il faut poursuivre sur les écrans restants ou s'arrêter à un périmètre intermédiaire.
Sur les applications que nous avons accompagnées, le gain le plus net ne vient pas du mode zoneless lui-même mais du nettoyage qu'il impose : abonnements non libérés, état dupliqué, et composants qui se réabonnaient à chaque interaction. C'est ce travail qui produit la différence mesurable.
Articles associes
Observabilité avec OpenTelemetry : instrumenter ce qui sert vraiment au diagnostic
Ajouter une bibliothèque de traces ne rend pas un système observable. Ce qui compte, c'est le choix des attributs, la propagation du contexte et la discipline sur les volumes stockés.