Module Federation : Micro-frontends Webpack 5

🏷️ Front-end 📅 08/04/2026 16:00:00 👤 Mezgani Said
Module-Federation Microfrontends Webpack Angular
Module Federation : Micro-frontends Webpack 5

Architecture micro-frontends scalable avec Module Federation : host/remote apps, partage de dépendances, routing fédéré et bonnes pratiques.

Introduction

Module Federation est une technologie Webpack qui permet de charger des applications Angular indépendantes dans une application hôte. C'est parfait pour les équipes distribuées travaillant sur des modules isolés tout en partageant les dépendances communes.

Cas d'usage : Pensez à une plateforme e-commerce où le panier, les produits et l'authentification sont des équipes séparées. Chacune déploie son code indépendamment, mais tout fonctionne ensemble dans l'app hôte.

Concept fondamental

Module Federation repose sur une architecture Host-Remote :

  • Host App : Application principale qui orchestre le chargement des remote apps
  • Remote Apps : Applications indépendantes exposant des modules réutilisables
  • Partage de dépendances : Angular, RxJS et autres libs chargés une seule fois
Avantage clé : Les équipes peuvent déployer indépendamment sans redéployer l'app entière. Les mises à jour sont transparentes pour l'utilisateur.

Configuration Host App

La host app configure ModuleFederationPlugin en spécifiant les remotes — c'est-à-dire, où charger les modules distants :

// webpack.config.js (Host App)
import { ModuleFederationPlugin } from '@angular-architects/module-federation/webpack';
import { share } from '@angular-architects/module-federation/build-tools';

export const config = {
  output: {
    uniqueName: 'host',  // Nom unique pour la host
    publicPath: 'auto',  // URLs relatives pour dev/prod
  },
  plugins: [
    new ModuleFederationPlugin({
      name: 'host',
      filename: 'remoteEntry.js',  // Fichier d'entrée
      remotes: {
        // Chemin vers les remote apps et leur module exposé
        userModule: 'user_module@http://localhost:4201/remoteEntry.js',
        productModule: 'product_module@http://localhost:4202/remoteEntry.js',
      },
      shared: share({  // Dépendances partagées
        '@angular/core': { singleton: true, strictVersion: true },
        '@angular/common': { singleton: true, strictVersion: true },
        'rxjs': { singleton: true, strictVersion: true },
      }),
    }),
  ],
};

Explication : Quand la host démarre, elle charge les fichiers remoteEntry.js des remotes. Ces fichiers indiquent quel code exposer et quelles dépendances partager.

Configuration Remote App

Chaque remote expose ses modules via exposes dans sa configuration Webpack :

// webpack.config.js (Remote App : user-module)
import { ModuleFederationPlugin } from '@angular-architects/module-federation/webpack';

export const config = {
  output: {
    uniqueName: 'user_module',  // Doit être unique
    publicPath: 'auto',
  },
  plugins: [
    new ModuleFederationPlugin({
      name: 'user_module',
      filename: 'remoteEntry.js',  // Généré à la racine du build
      exposes: {
        // Chemin interne → nom exporté
        './UserModule': './src/app/user/user.module.ts',
        './UserService': './src/app/user/user.service.ts',
      },
      shared: {  // Même dépendances que la host
        '@angular/core': { singleton: true, strictVersion: true },
        '@angular/common': { singleton: true, strictVersion: true },
        'rxjs': { singleton: true, strictVersion: true },
      },
    }),
  ],
};

À retenir : L'URL doit pointer vers le remoteEntry.js généré. En production, ce sera l'URL CDN ou du serveur Nginx de la remote app.

Stratégie de partage des dépendances

L'intérêt majeur de Module Federation est d'éviter les téléchargements multiples. La host et les remotes partagent Angular, RxJS et autres libs :

// Configuration partagée optimale
shared: {
  '@angular/core': {
    singleton: true,     // Une seule instance dans le navigateur
    strictVersion: true, // Même version partout
    requiredVersion: '18.0.0',  // Version minimale requise
  },
  '@angular/common': { singleton: true, strictVersion: true },
  '@angular/forms': { singleton: true, strictVersion: true },
  'rxjs': {
    singleton: true,
    strictVersion: false,  // RxJS tolère les versions mineures différentes
  },
  'axios': { singleton: true },  // Pour les services HTTP personnalisés
}
Attention : Si la host utilise Angular 18 et une remote Angular 17, l'app peut crasher. Synchronisez les versions ou utilisez strictVersion: false avec prudence.

Intégration du routeur

Chargez les modules remotes via le routeur Angular :

// app.routes.ts (Host App)
import { loadRemoteModule } from '@angular-architects/module-federation-runtime';

export const routes: Routes = [
  {
    path: 'users',
    loadChildren: () =>
      loadRemoteModule({
        type: 'module',
        remoteEntry: 'http://localhost:4201/remoteEntry.js',
        exposedModule: './UserModule',
      }).then(m => m.UserModule),
  },
  {
    path: 'products',
    loadChildren: () =>
      loadRemoteModule({
        type: 'module',
        remoteEntry: 'http://localhost:4202/remoteEntry.js',
        exposedModule: './ProductModule',
      }).then(m => m.ProductModule),
  },
];

Avantage : Chaque module remote se charge dynamiquement quand l'utilisateur navigue vers sa route. Zéro impact au démarrage initial.

Conclusion

Module Federation transforme la façon de développer les grandes applications Angular. Les équipes travaillent indépendamment, déploient en parallèle et partagent les ressources intelligemment.

Prochaines étapes :
  • Utilisez @angular-architects/module-federation pour simplifier la configuration
  • Documentez les contrats entre host et remotes (versions, modules exposés)
  • Mettez en place un système de versionning pour les remotes exposés
  • Testez les fallbacks en cas d'absence d'une remote (loading states)