📧 Reste informé(e) !

Reçois les derniers articles et conseils EasyAngularKit directement dans ta boîte mail.

S'inscrire gratuitement

~7 min de lecture

Angular 22 : le guide complet de la release signal-first

Ça y est, Angular 22 est sorti. Si Angular 21 posait les fondations (zoneless par défaut, Vitest, Tailwind natif), la v22 assume pleinement la direction prise depuis la v17 : moins de magie, signals partout, et un grand ménage dans les APIs historiques.

C'est une release de consolidation. Plusieurs features longtemps expérimentales passent en stable, des choix par défaut changent (parfois de façon breaking), et tout un pan d'API ViewEngine et NgModule disparaît pour de bon.

Dans cet article, on passe en revue ce qui change concrètement :

  • OnPush devient le change detection par défaut,
  • les Signal Forms rejoignent l'API publique,
  • FetchBackend devient le backend HTTP par défaut,
  • le nouveau décorateur @Service et la fonction injectAsync(),
  • le support des outils MCP côté web,
  • un compilateur plus strict,
  • et la suppression d'un paquet d'APIs dépréciées.

Petit prérequis avant de commencer : la v22 demande TypeScript 6.0 minimum. Les versions antérieures de TS ne sont plus supportées, à garder en tête avant de lancer la migration.


1. OnPush devient la stratégie par défaut

C'est le changement de comportement le plus impactant de la v22.

Jusqu'ici, un composant sans changeDetection explicite utilisait ChangeDetectionStrategy.Default. En Angular 22, un composant dont la stratégie est undefined bascule automatiquement en OnPush.

import { Component } from '@angular/core';

@Component({
  selector: 'app-card',
  templateUrl: './card.html',
  // Aucune stratégie précisée : OnPush s'applique automatiquement en v22
})
export class Card {}

Concrètement, le framework pose la change detection précise et basée sur les signals comme norme par défaut. Dans la majorité des cas modernes (signals, input(), composants déjà en OnPush), tu ne verras aucune différence, c'est même ce que tu voulais.

Si tu as encore des composants qui s'appuient sur le comportement « tout vérifier » de Default (mutation d'objets, setTimeout qui modifie l'état sans passer par un signal), tu peux explicitement revenir en arrière avec le nouvel alias Eager :

import { ChangeDetectionStrategy, Component } from '@angular/core';

@Component({
  selector: 'app-legacy-widget',
  templateUrl: './legacy-widget.html',
  changeDetection: ChangeDetectionStrategy.Eager, // ancien comportement "Default"
})
export class LegacyWidget {}

Eager est l'alias cosmétique de l'ancien Default. Le message est clair : OnPush n'est plus une optimisation, c'est la base.


2. Les Signal Forms passent en API publique

Le feuilleton des Signal Forms touche à sa fin. Après plusieurs minors où l'API se stabilisait (cf. la 21.2), les Signal Forms graduent officiellement dans l'API publique en v22.

On reste sur l'API form() introduite en 21.x, qui infère les types depuis le modèle :

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { form, submit } from '@angular/forms/signals';

@Component({
  selector: 'app-profile',
  templateUrl: './profile.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class Profile {
  protected readonly profileForm = form({
    email: '',
    age: 0,
  });

  protected onSubmit(): void {
    submit(this.profileForm, {
      action: (value) => this.save(value),
    });
  }

  private save(value: { email: string; age: number }): void {
    // ...
  }
}

La v22 ajoute trois capacités utiles :

  • reloadValidation() pour redéclencher manuellement une validation asynchrone (par exemple après un retry réseau) ;
  • une option de debounce dans validateAsync et validateHttp ;
  • la méthode FieldState.getError() pour récupérer une erreur précise d'un champ.
// Lire une erreur ciblée sur un champ
const emailError = this.profileForm.email().getError('async');

// Forcer une revalidation
this.profileForm.email().reloadValidation();

Côté validation, attention à un breaking change : les règles min et max n'acceptent plus de valeurs string. Il faut désormais passer un number ou null.

Si tu attendais la stabilisation pour migrer tes formulaires en production, c'est le moment de t'y mettre sérieusement.


3. FetchBackend devient le backend HTTP par défaut

Grosse simplification côté HTTP : FetchBackend est maintenant l'implémentation par défaut du HttpClient. Plus besoin d'opt-in explicite via withFetch().

Conséquence directe : withFetch() est déprécié et peut être retiré sans risque.

import { provideHttpClient } from '@angular/common/http';

// Avant (v21)
provideHttpClient(withFetch());

// v22 : fetch est déjà le défaut
provideHttpClient();

Deux autres évolutions à connaître :

  1. reportProgress est déprécié, remplacé par deux options plus explicites : reportUploadProgress et reportDownloadProgress.

  2. Le suivi de progression d'upload repose sur XHR. Si tu en as besoin, il faut explicitement repasser sur le backend XHR, qui utilise HttpXhrBackend :

    import { provideHttpClient, withXhr } from '@angular/common/http';
    
    provideHttpClient(withXhr());
    

Enfin, côté SSR, une taille de buffer maximale a été introduite pour les requêtes fetch, afin d'éviter de gonfler la mémoire serveur sur de grosses réponses.


4. Le décorateur @Service et injectAsync()

La v22 introduit un nouveau décorateur @Service. Dans la lignée du découplage NgModule, il offre une sémantique plus claire que @Injectable() pour déclarer un service applicatif.

Côté injection, la nouvelle fonction injectAsync() permet de résoudre une dépendance de manière asynchrone, utile pour le lazy loading de providers ou les ressources chargées dynamiquement.

import { injectAsync, Service } from '@angular/core';

@Service()
export class CatalogService {
  private readonly engine = injectAsync(() =>
    import('./catalog-engine').then((m) => m.CatalogEngine),
  );
}

À cela s'ajoutent plusieurs raffinements côté core :

  • caching des resource() en SSR : les ressources résolues côté serveur ne sont plus refetchées à l'hydratation ;
  • bootstrap dans un shadow root désormais supporté ;
  • dé-duplication des host directives ;
  • support des IdleRequestOptions pour l'Idle service.

5. Support des outils MCP côté web

Angular 22 ajoute le support des Web MCP Tools. Le Model Context Protocol devient un citoyen de première classe pour connecter les outils d'IA au contexte de ton application et de ta codebase.

C'est dans l'air du temps : après le tooling pensé pour l'IA (schematics, llms.txt), Angular câble une brique standard pour les agents qui consomment et manipulent le code. Si tu construis des intégrations IA autour de ton app, c'est une porte d'entrée officielle plutôt qu'un bricolage maison.


6. Un compilateur (beaucoup) plus strict

La v22 muscle l'analyse statique des templates. Plusieurs diagnostics se déclenchent désormais sur les projets existants, attends-toi à des erreurs de compilation à la mise à jour :

  • nullishCoalescingNotNullable et optionalChainNotNullable : Angular te prévient quand tu utilises ?? ou ?. sur une valeur qui ne peut jamais être null ou undefined (code mort) ;
  • les éléments qui matchent plusieurs sélecteurs lèvent désormais une erreur à la compilation ;
  • les attributs préfixés par data- ne bindent plus d'inputs ni d'outputs ;
  • lier un même target en input et output lève une erreur ;
  • les variables in lèvent une erreur dans les expressions de template.

Bonne nouvelle en contrepartie : le type narrowing s'améliore. La navigation sûre (?.) affine désormais correctement le type des valeurs nullables, et l'optional chaining renvoie bien undefined.

@if (user()?.profile; as profile) {
  {{ profile.displayName }}
}

Ces diagnostics peuvent piquer au moment du ng update, mais ils révèlent du code mort ou des bindings ambigus. C'est un bon ménage.


7. Le Router évolue

Plusieurs ajustements côté routing, dont un changement de défaut à surveiller :

  • paramsInheritanceStrategy passe à 'always' par défaut (au lieu de 'emptyOnly'). Les enfants héritent désormais systématiquement des params et data des parents ;
  • dans un CanMatchFn, le paramètre currentSnapshot devient obligatoire, et canMatch reçoit un ActivatedRouteSnapshot partiel ;
  • nouveau support de browserUrl sur les router links ;
  • nouvelle option unmatchedInputBehavior et un paramètre options pour withComponentInputBinding ;
  • TitleStrategy.getResolvedTitleForRoute() renvoie maintenant string | undefined (fini le any).

Et un retrait : provideRoutes() disparaît, utilise provideRouter() ou le token ROUTES.

import { provideRouter } from '@angular/router';

// Avant : provideRoutes(routes)
// v22 :
provideRouter(routes);

8. Le grand ménage : APIs supprimées

La v22 assume la suppression d'un paquet d'APIs dépréciées de longue date. Si ton app traîne du legacy, c'est ici que ça va casser :

API supprimée Remplacement
ComponentFactoryResolver / ComponentFactory Passer la classe du composant directement (createComponent())
createNgModuleRef() createNgModule()
ChangeDetectorRef.checkNoChanges() fixture.detectChanges() dans les tests
provideRoutes() provideRouter() ou ROUTES
Intégration Hammer.js Implémentation custom des gestes
getAngularLib() / setAngularLib() getAngularJSGlobal() / setAngularJSGlobal()

À noter aussi : appRef.bootstrap() n'accepte plus any comme second argument (et l'élément ne peut plus être nullable), et les animations de leave ne sont plus limitées aux éléments réellement retirés du DOM.


9. En résumé : ce qu'il faut retenir

Changement Impact Action
OnPush par défaut Élevé Vérifier les composants en Default, sinon Eager
Signal Forms stables Élevé Migrer les formulaires, min/max en number
FetchBackend par défaut Élevé Retirer withFetch(), migrer reportProgress
TypeScript 6 minimum Élevé npm i -D typescript@6 avant la migration
Compilateur plus strict Moyen Corriger les diagnostics au build
Router (paramsInheritance, etc.) Moyen Vérifier l'héritage des params et CanMatchFn
@Service + injectAsync() Faible Adopter progressivement
Web MCP Tools Faible Pour les intégrations IA
Suppression APIs legacy Variable Suivre la table de remplacement

Pour mettre à jour :

ng update @angular/core@22 @angular/cli@22

Les schematics de migration gèrent une bonne partie du travail automatiquement, notamment les renommages d'API. Mais vu le nombre de changements de défaut (OnPush, FetchBackend, paramsInheritanceStrategy), prévois une passe de tests sérieuse derrière.

Angular 22, c'est la confirmation d'un cap : signal-first, strict par défaut, et débarrassé de son héritage ViewEngine. Si tu es déjà en zoneless avec signals et OnPush, la migration sera quasi indolore. Sinon, c'est l'occasion de solder la dette.

📧 Reste informé(e) !

Reçois les derniers articles et conseils EasyAngularKit directement dans ta boîte mail.

S'inscrire gratuitement

AngularKit

Suite d'outils pour développeurs Angular francophones. Apprends, modernise tes réflexes, audite ta codebase.

Produits

Contact

Légal

© 2026 AngularKit. Tous droits réservés.