Angular standalone components : migration complète

🏷️ Front-end 📅 12/04/2026 21:00:00 👤 Mezgani said
Angular Standalone Angular 17 Migration
Angular standalone components : migration complète

Migrez votre application Angular vers les standalone components : abandonnez les NgModules et simplifiez votre architecture avec cette approche moderne.

Le problème des NgModules

Depuis Angular 2, les NgModules servent de conteneurs pour regrouper composants, directives, pipes et services. Si ce système est puissant, il souffre de plusieurs inconvénients :

  • Boilerplate : chaque composant doit être déclaré dans un module
  • Lisibilité : les dépendances d'un composant sont dans un autre fichier
  • Compilation : les modules augmentent le temps de compilation
  • Tree-shaking : un module entier est inclus même si on utilise un seul composant

Concept des standalone components

Un composant standalone est auto-suffisant : il déclare ses propres dépendances dans son décorateur @Component, sans avoir besoin d'un NgModule parent.

// Composant classique (nécessite un NgModule)
@Component({
  selector: 'app-user-card',
  template: `...`
  // Dépendances déclarées dans AppModule ou UserModule
})
export class UserCardComponent {}

// Composant standalone (auto-suffisant)
@Component({
  selector: 'app-user-card',
  standalone: true,
  imports: [CommonModule, RouterLink, DatePipe], // dépendances ici
  template: `...`
})
export class UserCardComponent {}

Créer un composant standalone

Avec Angular CLI 17+, les composants sont standalone par défaut :

# Nouveau composant standalone (défaut depuis Angular 17)
ng generate component user-profile

# Forcer l'ancien style (avec module)
ng generate component user-profile --no-standalone

Un composant standalone peut importer d'autres composants standalone, des modules Angular (CommonModule, FormsModule), ou des modules tiers :

@Component({
  selector: 'app-dashboard',
  standalone: true,
  imports: [
    // Autres composants standalone
    UserCardComponent,
    ChartComponent,
    // Modules Angular intégrés
    NgIf,
    NgFor,
    AsyncPipe,
    // Ou en bloc
    CommonModule,
    // Modules tiers
    MatButtonModule,
    ReactiveFormsModule
  ],
  template: `
    <app-user-card [user]="user" />
    <app-chart [data]="chartData" />
  `
})
export class DashboardComponent {}

Bootstrap d'une app standalone

Une application entièrement standalone se bootstrap sans AppModule :

// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { appConfig } from './app/app.config';

bootstrapApplication(AppComponent, appConfig)
  .catch(console.error);

// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideHttpClient(),
  ]
};

Migration automatique avec ng generate

Angular fournit un schematic de migration en 3 étapes :

# Étape 1 : Convertir les composants, directives et pipes en standalone
ng generate @angular/core:standalone

# Choisir l'option "Convert all components, directives and pipes"
# Puis choisir "Remove unnecessary NgModule classes"
# Puis choisir "Bootstrap the application using standalone APIs"
A retenir : La migration automatique gère correctement ~95% des cas. Vérifiez manuellement les modules avec des providers de services (forRoot, forChild) qui peuvent nécessiter une adaptation.

Lazy loading sans modules

Avant les standalone components, le lazy loading nécessitait un module dédié. Désormais, on charge directement un composant :

// routes.ts
import { Routes } from '@angular/router';

export const routes: Routes = [
  {
    path: 'dashboard',
    // Ancien style : loadChildren: () => import('./dashboard/dashboard.module')
    loadComponent: () => import('./dashboard/dashboard.component')
      .then(m => m.DashboardComponent)
  },
  {
    path: 'admin',
    loadChildren: () => import('./admin/admin.routes')
      .then(m => m.adminRoutes)
  }
];
Note : loadComponent charge un seul composant en lazy. loadChildren peut pointer vers un tableau de routes (fichier *.routes.ts) pour lazy-loader un groupe de routes sans module.