Retour au blog

Micro Frontends : Comment Scaler les Applications Frontend Avec une Architecture Modulaire

Salut HaWkers, si vous travaillez dans une entreprise avec de grandes équipes frontend ou sur un monolithe difficile à maintenir, vous avez probablement entendu parler des micro frontends. Cette architecture promet d'apporter au frontend les mêmes avantages que les microservices ont apportés au backend.

Mais est-ce que ça vaut le coup ? Et comment implémenter de manière à ce que ça ne devienne pas un cauchemar ? Explorons cela en profondeur.

Qu'est-ce Que les Micro Frontends

Les micro frontends sont une architecture où une application web est divisée en parties plus petites et indépendantes, chacune développée, testée et déployée séparément.

Analogie simple :

  • Monolithe frontend = Un magasin où tous les rayons partagent la même caisse
  • Micro frontends = Un centre commercial où chaque boutique opère indépendamment

Caractéristiques principales :

  1. Indépendance de déploiement - Chaque partie peut être mise à jour sans affecter les autres
  2. Autonomie d'équipe - Différentes équipes peuvent travailler sur différentes parties
  3. Agnosticisme technologique - Chaque partie peut utiliser des technologies différentes
  4. Isolation des pannes - Les problèmes dans une partie ne font pas tomber tout le système

🏗️ Contexte : Le terme a été inventé en 2016, mais a gagné en popularité à partir de 2019 quand des entreprises comme IKEA, Spotify et DAZN ont partagé leurs expériences.

Quand Utiliser les Micro Frontends

Avant d'adopter cette architecture, vous devez être sûr qu'elle résout un vrai problème :

Signes Que Vous en Avez Besoin

Indicateurs organisationnels :

  • Plusieurs équipes travaillant sur le même frontend
  • Conflits de merge constants
  • Déploiement bloqué en attendant d'autres features
  • Temps de build/test très long
  • Difficulté d'onboarding des nouveaux devs

Indicateurs techniques :

  • Application avec des centaines de milliers de lignes de code
  • Bundle size très grand
  • Performance de développement dégradée
  • Tests trop lents

Signes Que Vous N'en Avez PAS Besoin

Quand éviter :

  • Petite équipe (moins de 10 développeurs frontend)
  • Application de taille moyenne
  • Domaine métier fortement couplé
  • Startup en phase initiale
  • Équipe sans expérience en architecture distribuée

Règle d'or : Si vous n'avez pas de problèmes clairs de scale ou d'organisation, les micro frontends vont ajouter de la complexité sans bénéfice.

Patterns d'Implémentation

Il existe plusieurs façons d'implémenter les micro frontends. Voyons les principales :

1. Module Federation (Webpack 5+)

L'approche la plus moderne et populaire actuellement :

// webpack.config.js du Host (Shell)
const { ModuleFederationPlugin } = require('webpack').container;

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'host',
      remotes: {
        // Charge le micro frontend panier depuis un autre serveur
        cartMfe: 'cartMfe@http://localhost:3001/remoteEntry.js',
        // Charge le micro frontend produits
        productsMfe: 'productsMfe@http://localhost:3002/remoteEntry.js',
      },
      shared: {
        react: { singleton: true, requiredVersion: '^18.0.0' },
        'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
      },
    }),
  ],
};

// webpack.config.js du Micro Frontend Panier
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'cartMfe',
      filename: 'remoteEntry.js',
      exposes: {
        './Cart': './src/components/Cart',
        './CartButton': './src/components/CartButton',
      },
      shared: {
        react: { singleton: true, requiredVersion: '^18.0.0' },
        'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
      },
    }),
  ],
};

Utilisation dans le Host :

// App.jsx dans le Host
import React, { Suspense } from 'react';

// Import dynamique du micro frontend distant
const RemoteCart = React.lazy(() => import('cartMfe/Cart'));
const RemoteProducts = React.lazy(() => import('productsMfe/ProductList'));

function App() {
  return (
    <div className="app">
      <header>Ma Boutique</header>

      <main>
        <Suspense fallback={<div>Chargement des produits...</div>}>
          <RemoteProducts />
        </Suspense>
      </main>

      <aside>
        <Suspense fallback={<div>Chargement du panier...</div>}>
          <RemoteCart />
        </Suspense>
      </aside>
    </div>
  );
}

2. Single-SPA

Framework dédié à l'orchestration des micro frontends :

// root-config.js
import { registerApplication, start } from 'single-spa';

// Enregistre le micro frontend de navigation
registerApplication({
  name: '@myorg/navbar',
  app: () => System.import('@myorg/navbar'),
  activeWhen: ['/'],
});

// Enregistre le micro frontend de produits (actif sur /products)
registerApplication({
  name: '@myorg/products',
  app: () => System.import('@myorg/products'),
  activeWhen: ['/products'],
});

// Enregistre le micro frontend de checkout (actif sur /checkout)
registerApplication({
  name: '@myorg/checkout',
  app: () => System.import('@myorg/checkout'),
  activeWhen: ['/checkout'],
});

start();

3. iFrames (Approche Simple)

Pour une isolation totale quand nécessaire :

// Composant wrapper pour micro frontend via iframe
function MicroFrontendFrame({ src, title, height = '600px' }) {
  return (
    <iframe
      src={src}
      title={title}
      style={{
        width: '100%',
        height,
        border: 'none',
      }}
      sandbox="allow-scripts allow-same-origin allow-forms"
    />
  );
}

// Utilisation
<MicroFrontendFrame
  src="https://checkout.myapp.com"
  title="Checkout"
  height="800px"
/>;

Communication Entre Micro Frontends

L'un des plus grands défis est de faire communiquer les micro frontends :

Event Bus

Pattern simple et efficace :

// eventBus.js - Partagé entre tous les MFEs
class EventBus {
  constructor() {
    this.events = {};
  }

  subscribe(event, callback) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(callback);

    // Retourne une fonction pour unsubscribe
    return () => {
      this.events[event] = this.events[event].filter((cb) => cb !== callback);
    };
  }

  publish(event, data) {
    if (this.events[event]) {
      this.events[event].forEach((callback) => callback(data));
    }
  }
}

// Singleton global
window.eventBus = window.eventBus || new EventBus();
export default window.eventBus;

Utilisation :

// Dans le MFE Produits
import eventBus from '@shared/eventBus';

function ProductCard({ product }) {
  const addToCart = () => {
    eventBus.publish('cart:add', {
      productId: product.id,
      quantity: 1,
    });
  };

  return (
    <div className="product">
      <h3>{product.name}</h3>
      <button onClick={addToCart}>Ajouter au Panier</button>
    </div>
  );
}

// Dans le MFE Panier
import eventBus from '@shared/eventBus';

function Cart() {
  const [items, setItems] = useState([]);

  useEffect(() => {
    const unsubscribe = eventBus.subscribe('cart:add', (data) => {
      setItems((prev) => [...prev, data]);
    });

    return unsubscribe;
  }, []);

  return <div>{/* Rend les articles */}</div>;
}

Custom Events (Natif Navigateur)

Alternative sans dépendances :

// Publier
window.dispatchEvent(
  new CustomEvent('cart:updated', {
    detail: { items: cartItems },
  })
);

// S'abonner
window.addEventListener('cart:updated', (event) => {
  console.log('Panier mis à jour :', event.detail.items);
});

Défis et Pièges

Les micro frontends apportent de la complexité. Soyez préparé :

1. Cohérence de l'UI

Problème : Chaque MFE peut avoir des styles différents.

Solution : Design System partagé

// @myorg/design-system - Package npm interne
export { Button } from './components/Button';
export { Card } from './components/Card';
export { theme } from './theme';
export { GlobalStyles } from './GlobalStyles';

2. Duplication des Dépendances

Problème : React chargé plusieurs fois.

Solution : Shared dependencies dans Module Federation

shared: {
  react: {
    singleton: true,
    requiredVersion: '^18.0.0',
    eager: true
  }
}

3. Performance

Problème : Multiples requêtes réseau.

Solutions :

  • Prefetch des MFEs critiques
  • Service workers pour le cache
  • CDN partagé

4. Tests End-to-End

Problème : Comment tester l'application complète ?

Solution : Environnement d'intégration dédié

# docker-compose.integration.yml
services:
  shell:
    build: ./packages/shell
    ports:
      - '3000:3000'

  cart-mfe:
    build: ./packages/cart
    ports:
      - '3001:3001'

  products-mfe:
    build: ./packages/products
    ports:
      - '3002:3002'

Outils de l'Écosystème

L'écosystème a beaucoup évolué en 2024-2025 :

Build et Bundling

Outil Usage Support MFE
Webpack 5 Module Federation natif Excellent
Vite vite-plugin-federation Bon
Rspack Module Federation Excellent
esbuild Personnalisation nécessaire Basique

Frameworks d'Orchestration

Framework Complexité Maturité
Single-SPA Élevée Élevée
Module Federation Moyenne Élevée
Qiankun Moyenne Moyenne
Luigi (SAP) Élevée Élevée

Outils Monorepo

Pour gérer plusieurs MFEs :

  • Nx - Le plus populaire, excellent support MFE
  • Turborepo - Performance, intégration Vercel
  • Lerna - Classique, moins de features
  • pnpm workspaces - Léger et efficace

Conclusion

Les micro frontends sont un outil puissant pour scaler des équipes et de grandes applications. Mais comme toute architecture distribuée, ils apportent une complexité qui doit être justifiée.

Utilisez si :

  • Vous avez plusieurs équipes indépendantes
  • L'application est vraiment grande
  • Problèmes clairs de scale
  • Équipe expérimentée en systèmes distribués

Évitez si :

  • Petite ou moyenne équipe
  • Application de taille normale
  • Vous cherchez une solution à des problèmes organisationnels
  • Pas d'expérience en architecture distribuée

Si vous décidez d'implémenter, commencez petit : extrayez un MFE, apprenez des défis, et scalez progressivement. La pire chose que vous puissiez faire est de tout migrer d'un coup.

Pour compléter vos connaissances en architectures frontend modernes, je recommande de jeter un œil à l'article Vite vs Webpack en 2025 où vous comprendrez les outils de build qui supportent ces architectures.

C'est parti ! 🦅

💻 Maîtrisez JavaScript Pour de Vrai

Les connaissances que vous avez acquises dans cet article ne sont qu'un début. Il y a des techniques, des patterns et des pratiques qui transforment les développeurs débutants en professionnels recherchés.

Investissez Dans Votre Avenir

J'ai préparé un matériel complet pour que vous maîtrisiez JavaScript :

Modes de paiement :

  • 1x de 9,90€ sans frais
  • ou 9,90€ comptant

📖 Voir le Contenu Complet

Commentaires (0)

Cet article n'a pas encore de commentaires. Soyez le premier!

Ajouter des commentaires