Ce qu'il faut retenir
Les micro-frontends répondent à un problème réel — mais uniquement au-delà d'un certain seuil de complexité organisationnelle et technique. Avant trois équipes frontend indépendantes et un découpage domaine métier clair, un monorepo bien structuré suffit et évite la surcharge architecturale.
Webpack Module Federation 5 reste le pattern de référence pour les projets Next.js B2B en 2026 : exposition de modules distants à la demande, partage de dépendances pour éviter la duplication de bundle, déploiement totalement indépendant par micro-app. L'intégration native avec Next.js 15 via le plugin @module-federation/nextjs-mf s'est considérablement simplifiée.
Les trois pièges les plus courants en production : la duplication de bundle React/ReactDOM quand le partage de dépendances est mal configuré, la régression des Core Web Vitals (LCP et CLS) due à l'hydration asynchrone des remotes, et l'absence de stratégie de design system partagé qui génère une incohérence visuelle progressive entre les micro-apps.
Le déploiement indépendant — le bénéfice central des micro-frontends — exige une infrastructure adaptée : CDN avec invalidation de cache granulaire par micro-app, versioning des remotes exposés, et un shell applicatif qui gère les fallbacks quand un remote est indisponible.
Micro-frontend 2026 : architecture et implémentation pour projets B2B
Le découpage d'une interface en micro-apps indépendantes n'est pas une tendance — c'est une réponse architecturale concrète aux contraintes des grandes applications B2B : équipes multiples, déploiements découplés, domaines métier distincts. Voici ce que j'ai appris en production.
Adapté à toute taille de structure
#Pourquoi les micro-frontends deviennent incontournables pour les grandes apps B2B
La question n'est pas «est-ce que les micro-frontends sont une bonne idée» — c'est «est-ce que votre situation spécifique justifie la complexité qu'ils introduisent». Cette nuance est essentielle, et j'y reviendrai en dernière section.
Pour les organisations qui réunissent les conditions d'application — et elles sont nombreuses parmi les ETI et grands comptes B2B — les micro-frontends répondent à des problèmes concrets qui ne peuvent pas être résolus autrement.
#Le problème du couplage au sein d'un frontend monolithique
Un frontend monolithique de grande taille développé sur 3 à 5 ans présente des caractéristiques prévisibles : des centaines de composants dans un même dépôt, des dizaines de développeurs qui se marchent dessus sur les mêmes fichiers, des builds de 20 minutes, des tests d'intégration qui durent une heure, et une mise en production unique qui bloque toutes les équipes si un seul module régresse.
Quand l'équipe Catalogue produits ne peut pas déployer sa nouvelle feature parce que l'équipe Checkout a cassé un test, ce n'est pas un problème de discipline — c'est un problème d'architecture. Le couplage technique entre des domaines métier distincts génère une friction opérationnelle qui croît exponentiellement avec la taille de l'équipe.
#Ce que les micro-frontends permettent réellement
La promesse centrale des micro-frontends tient en trois points :
Autonomie d'équipe : chaque équipe possède son micro-frontend de bout en bout (design, développement, CI/CD, monitoring). Elle peut déployer en production à tout moment sans coordination avec les autres équipes. Cette autonomie réduit la charge cognitive collective et accélère la vélocité de chaque stream.
Découpage domaine métier : chaque micro-frontend correspond à un bounded context du domaine métier — Catalogue, Checkout, Espace client, Dashboard analytics, Administration. Ce découpage aligne l'architecture frontend sur l'architecture microservices du backend, créant une cohérence systémique.
Déploiements indépendants : une micro-app peut être redeployée sans toucher au shell ni aux autres remotes. Un bug en production sur le module Facturation n'impacte pas le module Commandes. Le blast radius d'une mauvaise mise en production est strictement limité à son scope.
Ces bénéfices sont réels — mais ils ont un coût d'entrée significatif que les équipes sous-estiment systématiquement. Ce coût, c'est la complexité infrastructurale, la cohérence transversale (design system, authentification, state partagé) et le surcoût de debugging sur des systèmes distribués.
Pour les équipes qui arrivent d'un monolithe et envisagent une migration, le passage aux micro-frontends s'inscrit souvent dans une stratégie plus large de refonte technique dont il faut évaluer le ROI global.
#Patterns d'implémentation : Module Federation, iframes, Web Components, monorepo splits
Quatre grandes approches coexistent en 2026, avec des profils de complexité et de cas d'usage très différents.
#Module Federation (Webpack 5 / Rspack)
Module Federation est le pattern dominant pour les projets Next.js et React en production. Il permet à une application (le host ou shell) de charger dynamiquement des modules exposés par d'autres applications (remotes), avec partage optionnel de dépendances communes (React, ReactDOM, design tokens).
L'avantage clé : les remotes sont des bundles JavaScript autonomes déployés indépendamment sur un CDN. Le shell charge le manifest de chaque remote au runtime, pas au build time — ce qui rend possible le déploiement indépendant sans rebuild du shell.
#iframes
L'approche la plus simple et la plus isolée : chaque micro-app tourne dans son propre iframe. L'isolation est totale (CSS, JavaScript, DOM). La communication inter-apps passe par postMessage.
Cette approche est sous-estimée pour des cas d'usage spécifiques : intégration de modules tiers dont on ne maîtrise pas le code, migration progressive d'applications legacy, outils d'administration internes où la performance n'est pas critique. SAP l'utilise massivement dans ses produits enterprise. L'inconvénient principal est l'impact sur les Core Web Vitals (chaque iframe génère un sous-contexte de rendu séparé) et la complexité de l'accessibilité.
#Web Components
Les Web Components (Custom Elements + Shadow DOM + HTML Templates) permettent d'encapsuler une micro-app dans un élément HTML custom (<product-catalog />) framework-agnostique. Un Web Component peut être développé en React, Vue ou Svelte et consommé par n'importe quel autre framework.
En B2B 2026, les Web Components sont pertinents pour exposer des modules à des équipes utilisant des stacks différentes (équipe React qui consomme un module Angular legacy, par exemple). La limitation reste l'intégration avec le SSR Next.js — les Web Components sont fondamentalement client-side, ce qui complique le rendu serveur et impacte le LCP.
#Monorepo splits (Turborepo / Nx)
Avant de passer aux micro-frontends à déploiement indépendant, une étape intermédiaire est souvent suffisante : découper le code en packages indépendants au sein d'un monorepo. Avec Turborepo ou Nx, chaque domaine métier vit dans son propre package avec ses propres tests, sa propre pipeline CI, tout en restant dans un déploiement coordonné.
Cette approche donne 80 % des bénéfices de l'isolation de code (autonomie d'équipe, tests indépendants, clear ownership) sans la complexité du chargement de remotes à runtime. Elle convient aux équipes de 2 à 8 développeurs frontend.
#Webpack Module Federation 5 avec Next.js : setup technique détaillé
Voici le setup concret que Nehos utilise en production sur les projets B2B de grande taille en 2026, avec Next.js 15 et le plugin officiel @module-federation/nextjs-mf.
#Architecture cible
shell-app/ # Next.js — host, routing principal, auth
catalogue-mfe/ # Next.js — remote, domaine Catalogue produits
checkout-mfe/ # Next.js — remote, domaine Checkout/Panier
dashboard-mfe/ # Next.js — remote, domaine Analytics/Reporting
shared-ui/ # Package — design system partagé (tokens, composants)
#Configuration du shell (host)
// shell-app/next.config.mjs
import { NextFederationPlugin } from '@module-federation/nextjs-mf';
const remotes = (isServer) => {
const location = isServer ? 'ssr' : 'chunks';
return {
catalogue: `catalogue@${process.env.CATALOGUE_MFE_URL}/_next/static/${location}/remoteEntry.js`,
checkout: `checkout@${process.env.CHECKOUT_MFE_URL}/_next/static/${location}/remoteEntry.js`,
dashboard: `dashboard@${process.env.DASHBOARD_MFE_URL}/_next/static/${location}/remoteEntry.js`,
};
};
export default {
webpack(config, options) {
config.plugins.push(
new NextFederationPlugin({
name: 'shell',
remotes: remotes(options.isServer),
shared: {
react: { singleton: true, requiredVersion: '^18.3.0' },
'react-dom': { singleton: true, requiredVersion: '^18.3.0' },
'@shared-ui/tokens': { singleton: true },
},
extraOptions: { skipSharingNextInternals: false },
})
);
return config;
},
};
#Configuration d'un remote (catalogue-mfe)
// catalogue-mfe/next.config.mjs
import { NextFederationPlugin } from '@module-federation/nextjs-mf';
export default {
webpack(config, options) {
config.plugins.push(
new NextFederationPlugin({
name: 'catalogue',
filename: 'static/chunks/remoteEntry.js',
exposes: {
'./ProductGrid': './src/components/ProductGrid',
'./ProductDetail': './src/components/ProductDetail',
'./CategoryNav': './src/components/CategoryNav',
},
shared: {
react: { singleton: true, requiredVersion: '^18.3.0' },
'react-dom': { singleton: true, requiredVersion: '^18.3.0' },
},
})
);
return config;
},
};
#Consommation dans le shell
// shell-app/src/app/catalogue/page.tsx
import dynamic from 'next/dynamic';
const ProductGrid = dynamic(
() => import('catalogue/ProductGrid').catch(() => import('./fallbacks/ProductGridFallback')),
{
loading: () => <ProductGridSkeleton />,
ssr: false, // ou true si le remote supporte le SSR
}
);
export default function CataloguePage() {
return (
<main>
<ProductGrid />
</main>
);
}
Le .catch() dans le dynamic import est critique : si le remote CDN est indisponible, le shell affiche un fallback plutôt que de crasher. Ce fallback peut être un squelette statique ou un composant minimal servi depuis le shell lui-même.
#Rspack comme alternative
Rspack (le bundler Rust-based compatible Webpack) supporte Module Federation depuis la version 0.6. Sur les projets avec des builds dépassant 5 minutes, la migration vers Rspack réduit le build time de 60 à 80 % — tout en gardant la même configuration Module Federation. Cette migration sera abordée dans un article dédié.
#Routing et navigation : gérer la cohérence entre micro-apps
Le routing est l'un des défis techniques les plus complexes en architecture micro-frontend. Chaque micro-app a son propre routeur interne, mais l'utilisateur doit percevoir une expérience de navigation unifiée.
#Approche 1 : routing centralisé dans le shell
Le shell Next.js possède l'intégralité des routes de l'application. Chaque route charge le composant correspondant depuis le bon remote. C'est l'approche la plus simple et la plus cohérente du point de vue utilisateur.
/catalogue/* → catalogue-mfe/ProductGrid, ProductDetail
/checkout/* → checkout-mfe/CartPage, PaymentPage
/dashboard/* → dashboard-mfe/AnalyticsPage
Le shell gère les transitions de route, le prefetching et le back/forward. Les remotes exposent des composants de page, pas des applications avec leur propre routeur.
#Approche 2 : routing délégué aux remotes
Chaque remote gère ses propres sous-routes. Le shell délègue tout ce qui commence par /catalogue/ au remote Catalogue, qui utilise son propre Next.js App Router. Cette approche offre plus d'autonomie aux équipes remote mais génère une complexité de synchronisation d'état de navigation entre le shell et le remote.
En pratique, l'approche 1 (routing centralisé) est préférable pour les projets où l'expérience utilisateur est critique. L'approche 2 convient mieux aux outils internes où chaque domain fonctionne de façon quasi-autonome (ex : backoffice multi-modules).
#Navigation programmatique cross-apps
Quand un remote doit déclencher une navigation vers une route appartenant à un autre remote (ex : le Catalogue redirige vers le Checkout après un ajout au panier), deux patterns sont possibles :
Event Bus : le remote émet un événement custom (CustomEvent('navigate', { detail: { to: '/checkout/cart' } })) que le shell écoute et traduit en navigation Next.js.
Callback props : le shell injecte une prop onNavigate dans chaque composant remote. Le remote l'appelle quand une navigation cross-app est nécessaire. Plus explicite, mais couplage légèrement plus fort.
Le pattern Event Bus est préférable dans les architectures où les remotes ne doivent pas connaître l'API du shell. Pour aller plus loin sur les stratégies de routing dans les projets Next.js App Router, l'article dédié détaille les options disponibles.
#Design system partagé : tokens, composants, versioning
Sans stratégie explicite de design system partagé, les micro-frontends dérivent inévitablement : chaque équipe prend des raccourcis visuels, les espacements divergent, les couleurs mutent légèrement d'un module à l'autre. Ce drift visuel est perceptible par les utilisateurs et coûteux à corriger rétrospectivement.
#Architecture recommandée
packages/
shared-ui/
tokens/ # Design tokens (couleurs, typo, spacing) — source de vérité
components/ # Composants React partagés (Button, Input, Modal, Table)
hooks/ # Hooks utilitaires partagés
styles/ # CSS global, reset, animations
Le package shared-ui est publié dans le registre npm interne (Verdaccio, GitHub Packages ou npm private) et consommé par tous les remotes comme dépendance classique. Il est configuré comme singleton dans la config Module Federation — une seule instance partagée à runtime, sans duplication.
#Design tokens comme source de vérité
Les design tokens (définissant les couleurs, typographies, spacings, breakpoints, ombres) doivent vivre dans un fichier source unique, idéalement synchronisé avec Figma via un plugin d'export (Style Dictionary, Token Pipeline).
// packages/shared-ui/tokens/index.ts
export const tokens = {
color: {
brand: { primary: '#1A56DB', secondary: '#0E9F6E' },
neutral: { 50: '#F9FAFB', 900: '#111928' },
semantic: { error: '#E02424', warning: '#C27803', success: '#057A55' },
},
spacing: { xs: '4px', sm: '8px', md: '16px', lg: '24px', xl: '40px' },
radius: { sm: '4px', md: '8px', lg: '16px', full: '9999px' },
shadow: { card: '0 1px 3px rgba(0,0,0,0.1)', modal: '0 20px 60px rgba(0,0,0,0.15)' },
} as const;
#Stratégie de versioning du design system
Le versioning sémantique (SemVer) est obligatoire pour le design system partagé. Les règles :
- Patch (1.0.x) : corrections de bugs, ajustements mineurs sans impact visuel
- Minor (1.x.0) : nouveaux composants ou nouvelles props rétrocompatibles
- Major (x.0.0) : changements breaking (renommage de composants, changement de tokens existants)
Les remotes épinglent une version majeure ("@shared-ui/tokens": "^1.0.0") et migrent vers la version majeure suivante lors d'un sprint dédié. Cette discipline évite les incompatibilités visuelles inattendues entre les équipes.
Cette approche s'intègre naturellement dans une stratégie monorepo avec Turborepo où le design system est un package workspace interne.
→ Vous évaluez vos options ? Utilisez notre estimateur de budget en ligne pour obtenir une fourchette en 2 minutes, ou consultez nos tarifs détaillés.
#State management cross-app : quelles solutions en 2026
Le state management dans une architecture micro-frontend est fondamentalement différent d'une application monolithique : il n'existe pas de store global unique accessible à toutes les micro-apps. Chaque remote a son propre contexte React, ses propres hooks, ses propres stores locaux.
#État local aux remotes (recommandé par défaut)
La règle de base : chaque remote gère son propre état local. Le remote Catalogue gère son état de filtres, de pagination, de sélection de produit. Le remote Checkout gère son état de panier, d'adresse, de paiement. Cet isolement est une force — il réduit les bugs de régression cross-modules.
#Partage d'état minimal via props et callbacks
Pour les données que le shell doit partager avec les remotes (identité de l'utilisateur connecté, tenant ID, permissions, langue), le pattern le plus simple est l'injection via props :
// shell-app — injection du contexte utilisateur dans le remote
<ProductGrid
userId={session.user.id}
tenantId={session.tenant.id}
locale={router.locale}
onAddToCart={(productId) => cartActions.add(productId)}
/>
Ce pattern est prévisible, testable et ne crée pas de couplage implicite entre les modules.
#Shared state via module fédéré
Pour les cas où plusieurs remotes doivent partager un état dynamique (le panier visible dans le header du shell et dans le checkout remote), le shell peut exposer un store partagé comme module fédéré :
// shell expose son store cart comme module
exposes: {
'./useCartStore': './src/stores/cartStore',
}
Le remote Checkout importe et utilise shell/useCartStore directement. Ce pattern fonctionne mais crée un couplage runtime entre le shell et le remote — à utiliser avec parcimonie.
#Event Bus pour les communications asynchrones
Un Event Bus basé sur CustomEvent (ou mitt comme bibliothèque légère) permet des communications découplées : le remote Catalogue émet cart:item-added avec le produit en payload, le shell (ou tout autre abonné) réagit en mettant à jour le compteur du panier dans le header.
En 2026, les React Server Components complexifient légèrement cette question : les RSC ne peuvent pas écouter des événements DOM. La frontière client/serveur dans chaque micro-app doit être pensée explicitement pour ne pas créer de conflits avec les patterns de communication cross-apps.
#Performance : les pièges à éviter (bundle duplication, hydration, Core Web Vitals)
Les micro-frontends peuvent considérablement dégrader les performances si les pièges classiques ne sont pas anticipés. Voici les trois problèmes que Nehos rencontre systématiquement lors d'audits d'applications micro-frontend existantes.
#Piège 1 : duplication de bundle React
Sans configuration explicite du partage de dépendances dans Module Federation, chaque remote charge sa propre copie de React, ReactDOM et des bibliothèques communes. Sur 4 micro-apps utilisant React 18 + React Query + date-fns, la duplication peut peser 800 Ko à 1,2 Mo de JavaScript supplémentaire — déclenchant immédiatement une dégradation du LCP et du TBT.
La correction : déclarer singleton: true pour React, ReactDOM et toute dépendance partagée dans la config Module Federation. Le singleton force l'utilisation d'une instance unique partagée entre le host et tous les remotes.
shared: {
react: { singleton: true, requiredVersion: '^18.3.0', eager: true },
'react-dom': { singleton: true, requiredVersion: '^18.3.0', eager: true },
'react-query': { singleton: true, requiredVersion: '^5.0.0' },
}
L'option eager: true sur React et ReactDOM force leur chargement dans le chunk initial plutôt qu'en lazy — évitant un flash de rendu lors de l'hydration.
#Piège 2 : hydration asynchrone et régression CLS
Les remotes chargés en lazy (via dynamic(() => import('remote/Component'))) génèrent un délai d'hydration visible pour l'utilisateur : le skeleton s'affiche, puis le composant réel apparaît et pousse le contenu environnant — déclenchant un Cumulative Layout Shift.
Corrections :
- Utiliser des skeletons avec des dimensions fixes correspondant au composant remote attendu
- Pré-allouer l'espace visuel avec
min-heightsur le conteneur du remote - Pour les composants above-the-fold, considérer le SSR du remote (possible avec
@module-federation/nextjs-mf+ configuration serveur) - Monitorer le CLS par micro-app avec des outils comme Vercel Speed Insights ou Sentry Performance
Pour une analyse complète des stratégies d'optimisation des Core Web Vitals sur Next.js, l'article dédié couvre les techniques avancées.
#Piège 3 : waterfalls de chargement en cascade
Le shell charge son JS → parse → exécute → découvre les remotes → charge les remotes JS → parse → exécute → affiche. Cette cascade peut ajouter 800 ms à 2 s de délai d'affichage perçu sur mobile.
Corrections :
<link rel="preload">sur lesremoteEntry.jsdes remotes critiques (above-the-fold)- Prefetch des remotes secondaires (
<link rel="prefetch">) au moment du hover ou de l'interaction qui précède leur affichage - Configurer des Resource Hints dans le
<Head>du shell pour les remotes prioritaires
Une architecture micro-frontend performante dans les Core Web Vitals nécessite de traiter le chargement des remotes avec le même niveau d'attention que l'optimisation des images ou du JavaScript first-party.
#Déploiement indépendant : Vercel, AWS CloudFront, Nginx proxy
Le déploiement indépendant est la raison d'être des micro-frontends. Sa mise en œuvre exige une infrastructure adaptée.
#Vercel : la solution la plus simple pour les équipes Next.js
Chaque micro-app est un projet Vercel distinct, avec sa propre URL de déploiement, son propre domaine de preview, sa propre pipeline CI/CD. Le shell référence les remotes via des variables d'environnement pointant vers les URLs Vercel.
# Variables d'environnement du shell sur Vercel
CATALOGUE_MFE_URL=https://catalogue-mfe.vercel.app
CHECKOUT_MFE_URL=https://checkout-mfe.vercel.app
DASHBOARD_MFE_URL=https://dashboard-mfe.vercel.app
Avantage : la Preview URL de chaque remote change à chaque déploiement. Le shell peut être configuré pour pointer vers une branche de preview spécifique pendant les tests d'intégration cross-teams. Vercel gère automatiquement l'invalidation de cache CDN à chaque déploiement.
#AWS CloudFront : contrôle maximal pour les architectures enterprise
Pour les projets avec des contraintes de souveraineté des données, de SLA contractuel ou de coût à grande échelle, AWS CloudFront offre un contrôle total :
# Routing CloudFront par micro-app
/catalogue/_next/* → S3 bucket catalogue-mfe (invalidation par déploiement)
/checkout/_next/* → S3 bucket checkout-mfe
/dashboard/_next/* → S3 bucket dashboard-mfe
/* → EC2/ECS shell-app (ou Lambda@Edge)
La gestion du cache est critique : chaque déploiement d'un remote doit invalider les fichiers modifiés dans CloudFront (aws cloudfront create-invalidation --paths '/catalogue/_next/*'). Sans invalidation, le shell charge des bundles remote obsolètes.
#Nginx proxy pour les environnements on-premise
Pour les clients en datacenter privé ou en cloud souverain OVH/Scaleway, Nginx permet d'implémenter le routing micro-frontend :
# nginx.conf
upstream shell { server shell-app:3000; }
upstream catalogue { server catalogue-mfe:3001; }
upstream checkout { server checkout-mfe:3002; }
server {
location /catalogue/_next/ { proxy_pass http://catalogue; }
location /checkout/_next/ { proxy_pass http://checkout; }
location / { proxy_pass http://shell; }
}
Chaque micro-app est un conteneur Docker indépendant, orchestré par Kubernetes ou Docker Compose. Les mises à jour rolling sont possibles par micro-app sans downtime du shell.
#Versioning des remotes et stratégie de rollback
En production, les remotes doivent être versionnés explicitement. Le shell ne doit jamais pointer vers latest — toujours vers une version précise validée en staging :
CATALOGUE_MFE_URL=https://catalogue-mfe.vercel.app/v2.4.1
En cas de régression après déploiement d'un remote, le rollback est immédiat : changer la variable d'environnement du shell vers la version précédente du remote, sans toucher au shell ni aux autres remotes. C'est l'un des bénéfices les plus tangibles de l'architecture — un rollback en 30 secondes sur un module isolé.
#Quand NE PAS faire du micro-frontend : les contre-indications pour PME/ETI
Après avoir décrit tout ce que les micro-frontends permettent de faire, c'est peut-être la section la plus utile de cet article.
La réalité de mes missions en 2025-2026 : sur 10 projets où la question des micro-frontends est posée, 7 n'en ont pas besoin. L'architecture ajoute une complexité réelle qui n'est justifiée que dans des conditions organisationnelles et techniques spécifiques.
#Contre-indication 1 : équipe frontend inférieure à 6 développeurs
Les micro-frontends sont une solution au problème de coordination entre équipes multiples. Si vous n'avez qu'une seule équipe frontend (même de 5 à 8 personnes), le problème n'existe pas. Un monorepo bien structuré avec Turborepo donne exactement les mêmes bénéfices d'isolation de code sans la complexité du chargement de remotes à runtime.
La règle pratique : en dessous de 3 équipes frontend indépendantes avec des roadmaps distinctes, un monorepo suffit.
#Contre-indication 2 : domaine métier non découpable
Les micro-frontends s'appuient sur un découpage de bounded contexts clair. Si les modules de votre application s'interconnectent fortement — si le Catalogue dépend du Checkout qui dépend du CRM qui modifie le Catalogue — le découpage en remotes isolés ne fait que déplacer la complexité de couplage du code vers les contrats inter-apps. Le résultat est souvent pire.
Avant d'envisager des micro-frontends, posez la question : «Peut-on déployer le module A sans redeployer le module B ?» Si la réponse est non 60 % du temps, l'architecture n'apportera pas le bénéfice attendu.
#Contre-indication 3 : startup ou application en phase de discovery
Dans les 12 à 18 premiers mois d'un produit, les frontières de domaine ne sont pas encore stabilisées. Les micro-frontends figent une architecture avant que vous sachiez où sont vraiment les frontières naturelles. La dette technique d'une mauvaise découpure est considérable — il faut parfois deux sprints complets pour fusionner deux remotes mal découpés.
La recommandation : démarrez en monolithe bien structuré. Quand les douleurs de coordination deviennent mesurables (builds bloquants, déploiements coordonnés pénibles, tests cross-modules instables), c'est le moment d'envisager l'extraction en remotes.
#Contre-indication 4 : absence de budget infrastructure
Maintenir 4 applications Next.js indépendantes au lieu d'une coûte 4x le budget infrastructure (CI/CD, monitoring, alerting, mise à jour des dépendances, gestion des incidents). Sur Vercel Pro, 4 projets distincts = 4 fois le quota de build minutes. Sur AWS, 4 fois les load balancers, health checks, et services associés.
Pour les PME et ETI dont l'infrastructure frontend est gérée par 1 à 2 personnes, ce surcoût opérationnel est souvent prohibitif. Un headless commerce B2B bien architecturé en Next.js monolithique bien structuré reste la recommandation Nehos pour les organisations de cette taille.
#Contre-indication 5 : absence d'expertise Module Federation en interne
Module Federation a une courbe d'apprentissage significative. Les erreurs de configuration (singletons mal configurés, circular dependencies, SSR/CSR mismatch) génèrent des bugs difficiles à diagnostiquer — les messages d'erreur sont souvent peu parlants et les stack traces traversent la frontière shell/remote.
Si l'équipe n'a jamais déployé Module Federation en production et n'a pas le budget pour un accompagnement technique initial (2 à 4 sprints de mise en place), le risque de sur-ingénierie est élevé. Dans ce cas, la refonte du site B2B en Next.js bien structuré est une décision d'architecture plus sûre et plus rentable.
#Le test des 5 questions
Avant de décider d'adopter une architecture micro-frontend, répondez honnêtement à ces 5 questions :
- Avez-vous au moins 3 équipes frontend avec des cycles de déploiement indépendants ?
- Votre domaine métier présente-t-il des bounded contexts clairement identifiables avec peu de dépendances transversales ?
- Les conflits de déploiement entre équipes représentent-ils une douleur mesurable aujourd'hui ?
- Votre équipe a-t-elle l'expertise Module Federation ou le budget pour l'acquérir ?
- Avez-vous le budget infrastructure pour maintenir N applications indépendantes ?
Si vous répondez non à 3 de ces 5 questions, les micro-frontends ne sont pas la bonne décision aujourd'hui. Revenez à cette checklist dans 12 mois — les conditions organisationnelles changent souvent plus vite que les architectures.