Front-end angularforall.com

- Angular 22 : toutes les nouveautés

Angular Angular-22 Signal-Forms Inject-Async Onpush Hydration-Incrementale Breaking-Changes Migration Service-Decorator Ssr Typescript Zoneless Reactive-Forms Performance
Angular 22 : toutes les nouveautés

Angular 22 : Signal Forms stable, injectAsync(), OnPush par défaut, hydration incrémentale automatique et suppressions legacy. Guide complet et migration v21 → v22.

Angular 22 : vue d'ensemble et calendrier

Angular 22 marque une nouvelle étape dans la transformation du framework : après des années à poser les bases des Signals, du zoneless et des composants standalone, cette version stabilise et consolide ce qui était encore expérimental. La RC.0 est sortie le 13 mai 2026, avec une version stable prévue pour la semaine du 1er juin 2026.

Le message central d'Angular 22 est clair : moins de boilerplate, plus de performances par défaut. L'équipe Angular ne se contente plus d'offrir des APIs réactives en opt-in — elle les impose comme standard pour les nouveaux projets, forçant une transition vers les meilleures pratiques dès la création.

Calendrier : Angular suit un rythme de 2 versions majeures par an. Angular 22 sort en juin 2026 (6 mois après Angular 21 de novembre 2025). La prochaine version majeure, Angular 23, est prévue pour novembre 2026.

Les 5 axes majeurs d'Angular 22

  • Signal Forms stable : les formulaires réactifs basés sur les Signals passent en API publique officielle
  • Injection modernisée : injectAsync() et le décorateur @Service simplifient drastiquement la DI
  • OnPush par défaut : la détection de changements performante devient le comportement standard des nouveaux composants
  • Hydration incrémentale automatique : le SSR devient encore plus performant sans configuration
  • Nettoyage des APIs legacy : suppression définitive de ComponentFactoryResolver, NgModuleRef, Hammer.js
Fonctionnalité Angular 21 Angular 22
Signal Forms Developer Preview API publique stable ✅
injectAsync() Non disponible Nouvelle API ✅
ChangeDetection par défaut Default (Zone.js) OnPush pour nouveaux composants ✅
Hydration incrémentale Opt-in Activée par défaut ✅
ComponentFactoryResolver Déprécié Supprimé ❌
TypeScript minimum 5.7+ 5.9+ ✅

Entrons dans le détail de chaque nouveauté, en commençant par la plus attendue : les Signal Forms stables.

Signal Forms : API publique stable

Les Signal Forms sont la fonctionnalité la plus attendue d'Angular 22. Après plusieurs mois en Developer Preview, elles passent en API publique stable dans Angular 22.0.0-next.11. C'est la refonte complète du système de formulaires d'Angular, entièrement basée sur les Signals.

Pourquoi Signal Forms révolutionne les formulaires Angular

Les ReactiveFormsModule et FormsModule existants reposent sur Observable et des patterns complexes à maintenir. Signal Forms apporte une API déclarative, synchrone et facilement testable — sans subscribe(), sans valueChanges, sans gestion manuelle de la mémoire.

// AVANT (Reactive Forms classique) — boilerplate important
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({ standalone: true, imports: [ReactiveFormsModule], ... })
export class LoginClassicComponent {
    form: FormGroup;

    constructor(private fb: FormBuilder) {
        this.form = this.fb.group({
            email:    ['', [Validators.required, Validators.email]],
            password: ['', [Validators.required, Validators.minLength(8)]],
        });
    }

    // Accès à la valeur → this.form.get('email')?.value
    // Vérifier la validité → this.form.valid
    // Erreur → this.form.get('email')?.hasError('required')
    submit() {
        if (this.form.valid) {
            console.log(this.form.value);
        }
    }
}
// APRÈS (Signal Forms Angular 22) — API signal-native
import { signalForm, field, required, email, minLength } from '@angular/forms/signal';

@Component({ standalone: true, imports: [SignalFormsModule], ... })
export class LoginSignalComponent {
    // Déclaration du formulaire avec schema de validation
    form = signalForm({
        email:    field('', [required(), email()]),
        password: field('', [required(), minLength(8)]),
    });

    // Accès direct via Signal (lecture synchrone)
    // this.form.fields.email.value()  → valeur actuelle
    // this.form.fields.email.valid()  → booléen de validité
    // this.form.fields.email.errors() → liste des erreurs

    submit() {
        if (this.form.valid()) {
            // getValue() retourne l'objet typé complet
            console.log(this.form.getValue());
        }
    }
}

Validation déclarative et FieldState

Angular 22 introduit FieldState avec la méthode getError() pour accéder aux erreurs de manière typée et sans string magic.

// Signal Forms : validation et accès aux erreurs typé
import { signalForm, field, required, email, minLength } from '@angular/forms/signal';

export class RegisterComponent {
    form = signalForm({
        username: field('', [required(), minLength(3)]),
        email:    field('', [required(), email()]),
        password: field('', [required(), minLength(8)]),
    });

    // Récupérer une erreur spécifique par clé (typé, pas de string magic)
    get usernameError(): string | null {
        const errors = this.form.fields.username.errors();
        if (!errors) return null;
        if (errors.required) return 'Le nom d\'utilisateur est requis';
        if (errors.minlength) return `Minimum ${errors.minlength.requiredLength} caractères`;
        return null;
    }

    // Option debounce — retarder la validation (nouvel en Angular 22)
    formWithDebounce = signalForm({
        search: field('', [required()], { debounce: 300 }),
    });
}

Interopérabilité CVA avec Signal Forms

Angular 22 améliore l'interopérabilité entre Signal Forms et les Control Value Accessors (CVA) existants, permettant d'utiliser vos composants de formulaires personnalisés sans réécriture.

// Composant custom compatible Signal Forms et Reactive Forms
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
    selector: 'app-custom-input',
    template: `<input [value]="value" (input)="onChange($event.target.value)" />`,
    providers: [{
        provide: NG_VALUE_ACCESSOR,
        useExisting: CustomInputComponent,
        multi: true,
    }],
})
export class CustomInputComponent implements ControlValueAccessor {
    value = '';
    onChange = (_: string) => {};
    onTouched = () => {};

    writeValue(val: string) { this.value = val; }
    registerOnChange(fn: (v: string) => void) { this.onChange = fn; }
    registerOnTouched(fn: () => void) { this.onTouched = fn; }
}

// Ce CVA fonctionne tel quel dans un signalForm() Angular 22
Migration : Les Signal Forms coexistent avec les Reactive Forms et Template-driven Forms existants. Aucune migration forcée — vous adoptez Signal Forms module par module, à votre rythme.

injectAsync() et injection moderne

Angular 22 introduit injectAsync(), une nouvelle fonction permettant d'injecter des dépendances de manière asynchrone dans un contexte d'injection Angular. C'est la réponse à un manque longtemps ressenti : les services qui s'initialisent de façon asynchrone (chargement de config, feature flags, connexion à une API).

injectAsync() : le cas d'usage

Classiquement, les services nécessitant une initialisation async obligeaient à utiliser des APP_INITIALIZER ou des workarounds complexes. injectAsync() simplifie ce pattern :

// Angular 22 — injectAsync() : injection asynchrone
import { injectAsync, Injectable, Component } from '@angular/core';

// Service avec initialisation asynchrone
@Injectable({ providedIn: 'root' })
export class FeatureFlagService {
    private flags: Record<string, boolean> = {};

    // Initialisation async : charge les flags depuis une API
    async init(): Promise<void> {
        const response = await fetch('/api/feature-flags');
        this.flags = await response.json();
    }

    isEnabled(flag: string): boolean {
        return this.flags[flag] ?? false;
    }
}

// Dans un composant ou un service — injectAsync attend la promesse
@Component({ standalone: true, ... })
export class FeatureComponent {
    // injectAsync() : injecte le service ET attend son init()
    // Le composant ne se monte qu'après la résolution
    readonly featureFlags = injectAsync(async () => {
        const svc = inject(FeatureFlagService);
        await svc.init();
        return svc;
    });
}

injectAsync() avec ordonnancement des requêtes

Angular 22 (next.10) introduit également un ordonnancement des métadonnées de requêtes pour garantir un ordre déterministe lors de l'injection de dépendances asynchrones multiples.

// Injection asynchrone avec ordonnancement garanti
import { injectAsync, inject } from '@angular/core';

export class DashboardComponent {
    // Les deux injectAsync() s'exécutent en parallèle
    // mais Angular garantit l'ordre de résolution
    readonly userProfile = injectAsync(async () => {
        const svc = inject(UserProfileService);
        return svc.loadCurrentUser();
    });

    readonly permissions = injectAsync(async () => {
        const svc = inject(PermissionsService);
        return svc.loadForCurrentUser();
    });
}

Le décorateur @Service : DI simplifiée

Introduit en Angular 22 (next.9), @Service est une alternative plus concise à @Injectable({ providedIn: 'root' }) pour les services de portée globale — le cas d'usage le plus courant.

// Angular 22 — @Service vs @Injectable comparaison

// ❌ AVANT (verbeux mais toujours valide)
import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class UserService {
    getUsers() { return fetch('/api/users'); }
}

// ✅ APRÈS (Angular 22 — @Service, plus concis)
import { Service } from '@angular/core';

@Service() // Équivalent exact à @Injectable({ providedIn: 'root' })
export class UserService {
    getUsers() { return fetch('/api/users'); }
}

// @Service avec factory sur classe abstraite (nouveau en Angular 22)
abstract class DataSource {
    abstract load(): Promise<unknown[]>;
}

@Service({ useFactory: () => new HttpDataSource() })
class DataProvider extends DataSource {
    load() { return fetch('/api/data').then(r => r.json()); }
}
@Service vs @Injectable : @Service ne remplace pas @Injectable — les deux coexistent. Utilisez @Service pour les services globaux simples, et gardez @Injectable pour les cas nécessitant un scope particulier (composant, module, route).

OnPush par défaut : performance native

L'une des décisions architecturales les plus significatives d'Angular 22 : la stratégie de détection de changements ChangeDetectionStrategy.OnPush devient la valeur par défaut pour les nouveaux composants. Concrètement, tout composant généré via ng generate component utilisera désormais OnPush automatiquement.

Pourquoi ce choix ?

L'équipe Angular considère OnPush comme la meilleure pratique depuis des années, mais elle restait opt-in. Les benchmarks montrent que OnPush réduit significativement le nombre de cycles de détection, surtout dans les grandes applications avec des arbres de composants profonds.

// Ce que génère `ng generate component dashboard` dans Angular 22
import { Component, ChangeDetectionStrategy } from '@angular/core';

@Component({
    selector:    'app-dashboard',
    standalone:  true,
    imports:     [],
    templateUrl: './dashboard.component.html',
    // OnPush est maintenant le défaut — plus besoin de l'ajouter manuellement
    changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DashboardComponent {}

Comportement OnPush : rappel essentiel

Avec OnPush, Angular ne vérifie le composant que dans quatre cas précis :

  • Un input a changé de référence (objet ou tableau remplacé, pas muté)
  • Un événement DOM a été déclenché dans le composant (click, input, etc.)
  • Un Observable souscrit avec async pipe a émis une nouvelle valeur
  • Un Signal utilisé dans le template a changé de valeur
// OnPush avec Signals — le duo parfait Angular 22
import { Component, ChangeDetectionStrategy, signal, computed } from '@angular/core';

@Component({
    selector: 'app-cart',
    standalone: true,
    changeDetection: ChangeDetectionStrategy.OnPush,
    template: `
        <!-- Les Signals déclenchent automatiquement la mise à jour -->
        <p>Articles : {{ itemCount() }}</p>
        <p>Total : {{ total() | currency:'EUR' }}</p>
        <button (click)="addItem()">Ajouter</button>
    `,
})
export class CartComponent {
    // Signals = source de vérité réactive
    private items = signal<{ price: number }[]>([]);

    // computed() se recalcule automatiquement quand items() change
    itemCount = computed(() => this.items().length);
    total     = computed(() => this.items().reduce((sum, i) => sum + i.price, 0));

    addItem() {
        // signal.update() → Angular détecte le changement même en OnPush
        this.items.update(list => [...list, { price: 9.99 }]);
    }
}

Cas où OnPush peut surprendre

Si vous mutez un objet au lieu de le remplacer, OnPush ne détectera pas le changement. C'est intentionnel — et c'est ce qui le rend performant.

// ⚠️ Piège classique avec OnPush — mutation vs remplacement
export class ListComponent {
    items = signal<string[]>([]);

    // ❌ FAUX — mutation directe : Angular ne détecte pas le changement
    addItemWrong(name: string) {
        const list = this.items();
        list.push(name); // mutation de l'array existant
        // Angular ne voit pas de changement de référence → pas de rendu
    }

    // ✅ CORRECT — remplacement de référence : signal.update() crée un nouveau tableau
    addItemCorrect(name: string) {
        this.items.update(list => [...list, name]);
        // Nouveau tableau → Angular détecte le changement → rendu déclenché
    }
}
Checklist migration vers OnPush :
  • Remplacer les mutations d'objets/tableaux par du remplacement de référence
  • Utiliser async pipe ou Signals pour les données asynchrones
  • Injecter ChangeDetectorRef.markForCheck() si vous avez des changements en dehors du contexte Angular
  • Tester chaque composant après activation d'OnPush

Hydration incrémentale par défaut

Angular 22 (next.8) active l'hydration incrémentale par défaut pour les applications SSR. Plus besoin de la configurer manuellement — elle s'active dès que vous utilisez Angular SSR, offrant des gains de performance immédiats sur le Time to Interactive (TTI).

Qu'est-ce que l'hydration incrémentale ?

L'hydration incrémentale permet à Angular d'hydrater les composants progressivement, au lieu de tout hydrater d'un coup au chargement. Les composants hors viewport ou non critiques sont hydratés seulement quand ils deviennent nécessaires.

// Angular 21 — hydration incrémentale : configuration manuelle requise
// app.config.ts
import { provideClientHydration, withIncrementalHydration } from '@angular/platform-browser';

export const appConfig: ApplicationConfig = {
    providers: [
        provideClientHydration(
            withIncrementalHydration() // Opt-in explicite requis
        ),
    ],
};
// Angular 22 — hydration incrémentale : activée automatiquement
// app.config.ts — plus besoin de withIncrementalHydration() !
import { provideClientHydration } from '@angular/platform-browser';

export const appConfig: ApplicationConfig = {
    providers: [
        provideClientHydration(), // L'hydration incrémentale est incluse par défaut
    ],
};

Contrôle granulaire avec @defer

L'hydration incrémentale s'intègre naturellement avec @defer pour hydrater les blocs de contenu de façon conditionnelle :

// Template Angular 22 — @defer + hydration incrémentale
// La section commentaires n'est hydratée qu'à la demande

<!-- Contenu principal : hydraté en priorité -->
<article>
    <h1>{{ article.title }}</h1>
    <p>{{ article.content }}</p>
</article>

<!-- Commentaires : hydratés seulement quand l'utilisateur scrolle jusqu'ici -->
@defer (on viewport; hydrate on interaction) {
    <app-comments [articleId]="article.id" />
} @placeholder {
    <div class="comments-placeholder">Chargement des commentaires...</div>
}

SSR : caching des ressources

Angular 22 améliore également le caching des ressources SSR. Les données chargées côté serveur sont sérialisées et transférées au client, évitant les double-fetch au moment de l'hydration.

// Angular 22 — resource() avec caching SSR automatique
import { resource, inject } from '@angular/core';
import { HttpClient }       from '@angular/common/http';

@Component({ standalone: true, ... })
export class ArticleComponent {
    private http = inject(HttpClient);

    // resource() avec SSR : les données sont cachées et transférées au client
    // Plus de double requête HTTP lors de l'hydration
    article = resource({
        loader: () => this.http.get<Article>('/api/articles/1').toPromise(),
        // Angular 22 : transfert automatique de l'état SSR → client
    });
}
Impact performance : L'hydration incrémentale par défaut peut réduire le Time to Interactive de 30 à 60% sur les pages riches en composants, car Angular ne bloque plus le thread principal pour hydrater des sections non visibles.

HTTP et Router : nouvelles options

Angular 22 apporte plusieurs améliorations ciblées au module HTTP et au Router, sans révolutions majeures mais avec des gains concrets pour les cas d'usage courants.

HTTP : reportUploadProgress et reportDownloadProgress

L'option reportProgress est dépréciée au profit de deux options distinctes et plus précises : reportUploadProgress et reportDownloadProgress.

// Angular 22 — suivi séparé upload et download
import { HttpClient, HttpEventType } from '@angular/common/http';

@Injectable({ providedIn: 'root' })
export class FileUploadService {
    constructor(private http: HttpClient) {}

    // ❌ DÉPRÉCIÉ en Angular 22 — reportProgress générique
    uploadOld(file: File) {
        return this.http.post('/api/upload', file, {
            reportProgress: true, // Déprécié
            observe: 'events',
        });
    }

    // ✅ NOUVEAU — options distinctes plus expressives
    uploadNew(file: File) {
        return this.http.post('/api/upload', file, {
            reportUploadProgress: true,   // Suivi progression upload
            reportDownloadProgress: false, // Pas besoin pour un upload simple
            observe: 'events',
        }).pipe(
            filter(e => e.type === HttpEventType.UploadProgress),
            map(e => Math.round(100 * e.loaded / (e.total ?? e.loaded))),
        );
    }

    // Téléchargement avec suivi progress
    downloadFile(url: string) {
        return this.http.get(url, {
            responseType: 'blob',
            reportDownloadProgress: true, // Suivi de la progression du download
            observe: 'events',
        });
    }
}

allowedHosts pour renderModule (SSR)

Angular 22 ajoute une option allowedHosts à renderModule pour renforcer la sécurité côté serveur en limitant les hôtes autorisés à déclencher le rendu SSR :

// Angular 22 — renderModule avec allowedHosts (sécurité SSR)
import { renderModule } from '@angular/platform-server';
import { AppModule } from './app/app.module';

// Sécuriser le rendu SSR : seuls ces hôtes peuvent déclencher le rendu
const html = await renderModule(AppModule, {
    document: '<!doctype html><html><body><app-root></app-root></body></html>',
    url: 'https://monsite.com/',
    // Nouveau en Angular 22 : protection contre les host-injection attacks
    allowedHosts: ['monsite.com', 'www.monsite.com'],
});

Router : paramsInheritanceStrategy par défaut

Angular 22 change la valeur par défaut de paramsInheritanceStrategy à 'always'. Cela signifie que les paramètres de route des parents sont maintenant hérités par les routes enfants sans configuration supplémentaire.

// Angular 22 — paramsInheritanceStrategy = 'always' par défaut

// Routes imbriquées — exemple
const routes: Routes = [{
    path: 'products/:categoryId',
    component: CategoryComponent,
    children: [{
        path: ':productId',
        component: ProductComponent,
        // ProductComponent peut maintenant accéder à categoryId
        // SANS configurer paramsInheritanceStrategy dans le router
    }],
}];

// Dans ProductComponent
@Component({ standalone: true, ... })
export class ProductComponent {
    private route = inject(ActivatedRoute);

    // ✅ Angular 22 : categoryId hérité automatiquement du parent
    categoryId = this.route.snapshot.params['categoryId'];
    productId  = this.route.snapshot.params['productId'];
}

Language Service : inlay hints pour les templates

Le language service Angular 22 (VS Code extension) supporte maintenant les inlay hints dans les templates — des suggestions de types affichées directement dans le code, similaires à ce que TypeScript offre dans les fichiers .ts.

Inlay hints : Dans un template @for (item of items; track item.id), le language service peut afficher le type inféré de item directement dans l'éditeur, sans avoir à chercher la définition de items.

Breaking changes et suppressions

Angular 22 procède à un nettoyage significatif d'APIs dépréciées depuis plusieurs versions. Ces suppressions sont les breaking changes les plus importants à anticiper avant la migration.

Suppressions majeures

API supprimée Remplacée par Depuis quelle version dépréciée
ComponentFactoryResolver ViewContainerRef.createComponent() Angular 13
createNgModuleRef() createEnvironmentInjector() Angular 14
Intégration Hammer.js Listeners natifs ou librairie tierce Angular 19
checkNoChanges() TestBed.flushEffects() en tests Angular 20
reportProgress (HttpClient) reportUploadProgress / reportDownloadProgress Angular 22

ComponentFactoryResolver : migration

// ❌ SUPPRIMÉ en Angular 22 — ComponentFactoryResolver
import { ComponentFactoryResolver, ViewContainerRef } from '@angular/core';

@Component({ ... })
export class OldDynamicComponent {
    constructor(
        private cfr: ComponentFactoryResolver, // ❌ N'existe plus en Angular 22
        private vcr: ViewContainerRef,
    ) {}

    create() {
        const factory = this.cfr.resolveComponentFactory(MyComponent); // ❌
        this.vcr.createComponent(factory); // ❌
    }
}

// ✅ CORRECT — Angular 13+ et Angular 22
import { ViewContainerRef } from '@angular/core';

@Component({ standalone: true, ... })
export class NewDynamicComponent {
    private vcr = inject(ViewContainerRef);

    create() {
        // Directement sur ViewContainerRef — plus de factory nécessaire
        const ref = this.vcr.createComponent(MyComponent);
        ref.setInput('title', 'Mon composant dynamique');
    }
}

Hammer.js : migration vers Pointer Events

// ❌ SUPPRIMÉ en Angular 22 — intégration Hammer.js

// angular.json — l'option HammerModule n'est plus disponible

// ✅ ALTERNATIVE — Pointer Events natifs ou HammerJS standalone
// Option 1 : Pointer Events natifs (recommandée)
@Component({
    template: `<div (pointerdown)="onPress($event)">Press me</div>`,
})
export class GestureComponent {
    onPress(event: PointerEvent) {
        console.log('Pressed at:', event.clientX, event.clientY);
    }
}

// Option 2 : utiliser HammerJS directement (sans intégration Angular)
import Hammer from 'hammerjs';

@Component({ ... })
export class HammerComponent implements AfterViewInit {
    @ViewChild('target') target!: ElementRef;

    ngAfterViewInit() {
        const mc = new Hammer(this.target.nativeElement);
        mc.on('swipeleft', () => this.onSwipeLeft());
    }
    onSwipeLeft() { console.log('Swiped left!'); }
}

Changements TypeScript

  • TypeScript 5.9 minimum — vérifier que votre tsconfig.json est compatible
  • Validation min/max stricte : les validateurs min() et max() n'acceptent plus les strings — utiliser des numbers directement
  • Template : safe navigation réduit les nullablesuser?.name est maintenant correctement inféré comme string | undefined (pas string | null | undefined)
  • Sélecteurs dupliqués : le diagnostic NG8023 génère maintenant une erreur (pas un warning) si deux composants ont le même sélecteur

Migrer de v21 à v22 : guide pas à pas

La migration d'Angular 21 vers Angular 22 est globalement fluide grâce aux schematics automatiques, mais les breaking changes listés ci-dessus nécessitent une attention particulière. Voici le processus recommandé.

Étape 1 : vérifier les prérequis

# Vérifier la version de Node.js (20.x ou 22.x recommandé pour Angular 22)
node --version

# Vérifier la version de npm
npm --version

# Angular 22 requiert TypeScript 5.9+
# Vérifier la version actuelle
npx tsc --version

Étape 2 : lancer ng update

# Mettre à jour Angular CLI en premier
npm install -g @angular/cli@22

# Dans votre projet : mettre à jour Angular core et CLI
ng update @angular/core@22 @angular/cli@22

# Si vous utilisez Angular Material
ng update @angular/material@22

# Si vous utilisez NgRx
ng update @ngrx/store@17 # NgRx v17 compatible Angular 22

Étape 3 : gérer les schematics automatiques

ng update lance automatiquement les schematics de migration. Vérifiez chaque fichier modifié :

# Après ng update, vérifier les changements dans le projet
git diff --stat

# Les schematics automatiques couvrent :
# - Suppression des imports ComponentFactoryResolver
# - Migration createNgModuleRef → createEnvironmentInjector
# - Ajout automatique de changeDetection: OnPush sur les nouveaux composants
# - Mise à jour des validateurs min/max (string → number)

Étape 4 : vérifier les breaking changes manuels

# Rechercher les usages de ComponentFactoryResolver restants
grep -r "ComponentFactoryResolver" src/ --include="*.ts"

# Rechercher les usages de createNgModuleRef
grep -r "createNgModuleRef" src/ --include="*.ts"

# Vérifier les imports HammerModule
grep -r "HammerModule" src/ --include="*.ts"

# Vérifier les usages de checkNoChanges()
grep -r "checkNoChanges" src/ --include="*.ts"

Étape 5 : tester et valider

# Lancer les tests unitaires
ng test

# Vérifier les types TypeScript
ng build --configuration=development

# Lancer les tests e2e (Playwright ou Cypress)
npx playwright test

# Build de production
ng build --configuration=production
Checklist migration Angular 22 :
  • Node.js 20.x ou 22.x installé
  • TypeScript 5.9+ dans tsconfig.json
  • ng update @angular/core@22 @angular/cli@22 exécuté
  • ComponentFactoryResolver remplacé par ViewContainerRef.createComponent()
  • HammerModule supprimé, listeners natifs ou HammerJS standalone à la place
  • Validateurs min()/max() passent des numbers (pas des strings)
  • Tests unitaires passants
  • Build production sans erreurs TypeScript
  • Tests e2e validés

Conclusion et perspectives

Angular 22 est une version de consolidation et de maturité. Elle ne réinvente pas le framework — elle finalise la transformation engagée depuis Angular 17. Les Signals, le zoneless, les composants standalone : tout est maintenant stable, performant et surtout activé par défaut.

Les points les plus impactants pour vos projets :

  • Signal Forms stable : si vous faites des formulaires complexes, c'est le moment de migrer
  • OnPush par défaut : vos nouveaux composants seront plus performants sans effort
  • Hydration incrémentale automatique : les apps SSR gagnent en TTI sans configuration
  • Breaking changes : anticipez la suppression de ComponentFactoryResolver si vous créez des composants dynamiques
Prochaine étape : Angular 23 est prévu pour novembre 2026. L'équipe travaille sur la stabilisation des resource() streams synchrones, l'amélioration du profiling, et potentiellement la sortie officielle d'Angular Signals hors de @angular/core pour une réutilisation dans d'autres contextes.

Pour aller plus loin, explorez nos articles connexes sur Angular 21, les Signal Forms en détail, l'injection inject() et les meilleures pratiques performance Angular. La v22 est disponible en RC depuis le 13 mai 2026 — vous pouvez déjà la tester sur vos projets non critiques.

Partager