Skip to content

YLemelin09/poc-cloud

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Guide D'Implementation Module Federation Pour Un Projet Existant

Ce repository sert de reference pour mettre en place une architecture micro-frontend Angular basee sur @angular-architects/module-federation, avec configuration runtime externe, menu centralise et deploiement Azure.

L'objectif de ce document est d'expliquer comment reproduire cette approche dans un autre projet existant, avec les contraintes suivantes :

  • un shell de type foundation
  • plusieurs remotes deja existants mais non prepares pour Module Federation
  • une route / qui charge elle aussi un remote dedie
  • une logique de menu provenant d'un repo ui-kit
  • un repo cloud-config-repo qui porte le manifest et le menu runtime
  • un state-bridge optionnel pour partager des contrats et de l'etat
  • un hebergement Azure pour le shell, les remotes et la configuration

Architecture cible

Le montage recommande est le suivant :

  • foundation : host Angular qui charge les remotes et gere la navigation globale
  • home-remote : nouveau remote charge sur la route /
  • remote-a, remote-b, remote-c : applications existantes rendues compatibles Module Federation
  • ui-kit : repo partage qui expose les composants de menu, les types et les helpers UI communs
  • cloud-config-repo : repo de fichiers statiques JSON qui contient menu.json et mf-manifest.json
  • state-bridge : package optionnel pour contrats partages, evenements et etat transverse

Le cycle de resolution est toujours le meme :

  1. foundation lit un runtime-config.json local
  2. ce fichier pointe vers cloud-config-repo
  3. foundation telecharge menu.json et mf-manifest.json
  4. le menu runtime construit la navigation visible
  5. le manifest runtime indique a Module Federation ou trouver les remotes
  6. a chaque navigation, foundation relit la configuration pour detecter nouveaux remotes, changements d'URL et changements de version

Repartition recommandee des repos

Pour reproduire ce modele dans un autre contexte, la separation la plus simple est :

  • un repo pour le shell
  • un repo par remote
  • un repo ui-kit
  • un repo cloud-config-repo
  • un repo state-bridge si vous avez besoin de contrats ou d'etat partages

Cette separation est importante car :

  • elle permet de deployer un remote sans rebuild du shell
  • elle permet de deployer une nouvelle configuration sans rebuild du shell
  • elle garde le menu et le manifest hors du bundle Angular du host

Etape 1 : preparer le shell foundation

Le shell doit rester une application Angular classique, mais avec un bootstrap runtime.

Le shell doit lui aussi etre configure pour Module Federation. Il ne suffit pas de configurer uniquement les remotes.

Installation minimale cote foundation :

  1. installer @angular-architects/module-federation
  2. installer @angular-builders/custom-webpack
  3. configurer angular.json pour utiliser les builders custom webpack
  4. ajouter un webpack.config.js
  5. declarer les dependances partagees Angular et les packages internes communs
  6. utiliser setManifest(...) et loadRemoteModule(...) dans le shell

Exemple minimal de webpack.config.js cote host :

const { share, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');

const federationConfig = withModuleFederationPlugin({
  name: 'foundation',
  library: {
    type: 'var',
    name: 'foundation'
  },
  shared: share({
    '@angular/core': { singleton: true, strictVersion: false, requiredVersion: 'auto' },
    '@angular/common': { singleton: true, strictVersion: false, requiredVersion: 'auto' },
    '@angular/common/http': { singleton: true, strictVersion: false, requiredVersion: 'auto' },
    '@angular/router': { singleton: true, strictVersion: false, requiredVersion: 'auto' },
    rxjs: { singleton: true, strictVersion: false, requiredVersion: 'auto' }
  })
});

module.exports = {
  ...federationConfig,
  output: {
    ...federationConfig.output,
    publicPath: '/'
  }
};

Exemple de points a verifier dans angular.json cote shell :

  • builder @angular-builders/custom-webpack:browser pour le build
  • builder @angular-builders/custom-webpack:dev-server pour le serve
  • customWebpackConfig.path qui pointe vers webpack.config.js

Principes a reprendre depuis ce PoC :

  • charger la configuration avant bootstrapApplication
  • injecter la configuration runtime dans Angular
  • construire les routes a partir du menu runtime
  • appeler setManifest(...) avec le manifest telecharge
  • relire la configuration a chaque navigation
  • afficher une bannere de refresh si la version d'un remote change dans le manifest

Le shell doit posseder au minimum :

  • un public/runtime-config.json
  • un loader de config runtime
  • un service shell qui gere le refresh de configuration
  • une fonction createAppRoutes(...)
  • une UI shell capable d'afficher le menu et la bannere de refresh

Etape 2 : faire en sorte que / soit aussi un remote

Dans ce PoC, / est encore une page locale du shell. Dans votre projet cible, il faut faire evoluer cette logique pour que / charge un remote dedie, par exemple homeRemote.

La convention recommandee est :

  • creer un repo home-remote
  • exposer ses routes via ./Routes
  • declarer une entree de menu avec route: "/" et remoteName: "homeRemote"
  • declarer homeRemote dans mf-manifest.json
  • adapter createAppRoutes(...) dans foundation pour autoriser un remote sur la route vide

Exemple de menu cible :

[
  {
    "id": "home",
    "label": "Accueil",
    "route": "/",
    "description": "Page d'accueil du domaine",
    "tag": "Remote",
    "remoteName": "homeRemote",
    "exposedModule": "./Routes"
  },
  {
    "id": "inventory",
    "label": "Inventory",
    "route": "/inventory",
    "description": "Stock et approvisionnement",
    "tag": "Remote",
    "remoteName": "inventoryRemote",
    "exposedModule": "./Routes"
  }
]

Exemple de manifest cible :

{
  "homeRemote": {
    "type": "module",
    "remoteEntry": "https://example-home-remote.azurestaticapps.net/remoteEntry.js?v=1.0.0",
    "version": "1.0.0"
  },
  "inventoryRemote": {
    "type": "module",
    "remoteEntry": "https://example-inventory.azurestaticapps.net/remoteEntry.js?v=2.3.1",
    "version": "2.3.1"
  }
}

Point d'attention :

  • dans le shell, la route Angular pour / correspond a path: ""
  • votre fabrique de routes doit donc accepter qu'un item de menu "/" soit transforme en remote racine au lieu d'etre reserve a une page locale

Etape 3 : rendre un remote existant compatible Module Federation

Pour chaque SPA existante qui doit devenir un remote :

  1. installer @angular-architects/module-federation
  2. installer @angular-builders/custom-webpack si ce n'est pas deja le cas
  3. configurer le builder Angular pour utiliser le webpack custom
  4. creer un webpack.config.js avec withModuleFederationPlugin(...)
  5. exposer ./Routes
  6. verifier que le remote produit bien remoteEntry.js

Exemple minimal de webpack.config.js :

const { share, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');

module.exports = withModuleFederationPlugin({
  name: 'inventoryRemote',
  filename: 'remoteEntry.js',
  exposes: {
    './Routes': './src/app/remote-entry/entry.routes.ts'
  },
  shared: share({
    '@angular/core': { singleton: true, strictVersion: false, requiredVersion: 'auto' },
    '@angular/common': { singleton: true, strictVersion: false, requiredVersion: 'auto' },
    '@angular/router': { singleton: true, strictVersion: false, requiredVersion: 'auto' },
    rxjs: { singleton: true, strictVersion: false, requiredVersion: 'auto' }
  })
});

Exemple minimal de routes exposees :

import { Routes } from '@angular/router';

export const remoteRoutes: Routes = [
  {
    path: '',
    loadComponent: () => import('../inventory-shell.component').then((m) => m.InventoryShellComponent)
  }
];

Etape 4 : adapter les applications existantes sans les reecrire

Pour un remote deja existant, l'idee n'est pas de tout refaire. Il faut surtout :

  • isoler son routeur interne sous une route racine path: ''
  • creer un fichier remote-entry/entry.routes.ts
  • verifier que les composants principaux peuvent etre charges via loadComponent ou loadChildren
  • retirer toute hypothese selon laquelle l'application est toujours servie seule sur /

Checklist de migration pour un remote existant :

  • conserver les pages et composants metier tels quels
  • ajouter une coquille RemoteShellComponent si besoin
  • exposer les routes a travers ./Routes
  • verifier les chemins relatifs et les assets
  • verifier les redirects internes
  • verifier les routerLink internes sous le prefixe du remote

Si le remote doit aussi continuer a tourner en autonome, gardez :

  • un AppComponent pour le mode standalone
  • un entry.routes.ts pour le mode federated

Etape 5 : integrer le repo ui-kit pour le menu

Dans votre projet cible, la logique de menu ne doit pas vivre en dur dans foundation.

Le repo ui-kit devrait idealement porter :

  • les types du menu
  • les helpers de validation ou normalisation
  • le composant visuel de navigation si vous voulez mutualiser le rendu
  • les tokens design communs

Le flux recommande est :

  1. cloud-config-repo/menu.json reste la source de verite runtime
  2. foundation telecharge ce JSON
  3. foundation le valide ou le normalise via un helper venant de ui-kit
  4. foundation l'affiche avec son layout shell

Le ui-kit n'est donc pas la source runtime des donnees, mais la source partagee de presentation et de typage.

Etape 6 : mettre en place cloud-config-repo

cloud-config-repo doit rester un repo de fichiers statiques, sans logique backend metier.

Structure minimale :

  • public/config/menu.json
  • public/config/mf-manifest.json

foundation/public/runtime-config.json doit simplement contenir :

{
  "configBaseUrl": "https://votre-config.azureedge.net/config"
}

Bonnes pratiques pour mf-manifest.json :

  • toujours declarer type
  • toujours declarer remoteEntry
  • toujours declarer version
  • si possible, versionner ou cache-buster aussi remoteEntry

La valeur version sert a detecter un changement a la navigation. L'URL versionnee du remoteEntry aide a forcer le navigateur a recuperer les nouveaux fichiers apres reload.

Etape 7 : reutiliser la mecanique runtime du shell

Les mecanismes de foundation de ce PoC doivent etre repris dans le projet cible :

  • chargement de runtime-config.json
  • chargement de menu.json et mf-manifest.json
  • injection de cette config dans le shell
  • construction dynamique des routes
  • setManifest(...)
  • refresh de configuration a chaque navigation
  • bannere de refresh si version change

Dans le projet cible, il est recommande de conserver la meme separation de responsabilites :

  • un loader pour la configuration runtime
  • un service shell pour le refresh et les comparaisons
  • un composant shell pour le layout et la bannere
  • une fabrique de routes pour transformer le menu runtime en routes Angular

Etape 8 : ajouter un nouveau remote plus tard

Une fois le systeme en place, ajouter un nouveau remote doit se limiter a :

  1. deployer le nouveau remote
  2. ajouter son entree dans mf-manifest.json
  3. ajouter son entree dans menu.json
  4. naviguer dans foundation

Le shell doit alors :

  • relire la configuration
  • afficher le nouveau lien
  • charger le nouveau remote sans rebuild du host

Etape 9 : state-bridge optionnel

Le state-bridge n'est pas obligatoire pour faire fonctionner Module Federation.

Il devient utile si vous avez besoin de :

  • contrats TypeScript partages
  • etat commun entre shell et remotes
  • evenements ou mutations transverses
  • mocks ou adaptateurs communs

Si vous l'ajoutez, traitez-le comme un package partage, pas comme un remote. Il doit etre :

  • versionne
  • buildable
  • reference comme dependance locale ou package interne
  • partage en singleton dans la config Module Federation

Si vous n'en avez pas besoin tout de suite, vous pouvez commencer sans lui puis l'ajouter plus tard.

Etape 10 : hebergement Azure

En production Azure, le montage recommande est :

  • foundation heberge sur Azure Static Web Apps ou Blob Storage static website
  • chaque remote heberge sur son propre endpoint statique
  • cloud-config-repo heberge comme fichiers statiques
  • ui-kit et state-bridge integres au build des applications qui les consomment

Exemples d'hebergement possibles :

  • Azure Static Web Apps
  • Azure Blob Storage static website
  • Azure CDN ou Front Door devant les assets

Points d'attention Azure :

  • activer CORS si foundation et cloud-config-repo sont sur des origines differentes
  • definir des regles de cache claires pour mf-manifest.json et menu.json
  • preferer cache-control: no-store ou TTL court pour les JSON de configuration
  • prevoir un versioning ou hash pour les remoteEntry.js et chunks

Sequence de deploiement recommandee

Pour deployer une nouvelle version d'un remote :

  1. incrementer sa version
  2. construire et publier le remote
  3. mettre a jour mf-manifest.json avec : la nouvelle version la nouvelle URL ou query string de remoteEntry
  4. redeployer cloud-config-repo

Pour ajouter un nouveau remote :

  1. rendre le repo compatible MF
  2. publier le remote
  3. l'ajouter au manifest
  4. l'ajouter au menu
  5. verifier la navigation dans le shell

Checklist de migration

  • creer ou adapter foundation
  • creer un home-remote pour /
  • rendre chaque SPA compatible MF
  • sortir le menu runtime dans cloud-config-repo
  • conserver les types et composants communs dans ui-kit
  • ajouter state-bridge seulement si necessaire
  • heberger shell, remotes et config comme assets statiques sur Azure
  • comparer les version de manifest a chaque navigation
  • afficher une bannere de refresh si une version change

Conseils pratiques

  • commencez par un shell + un seul remote avant de brancher tous les domaines
  • rendez d'abord un remote existant compatible MF, puis industrialisez la recette
  • gardez cloud-config-repo tres simple
  • ne faites pas porter au shell des routes compilees en dur si vous voulez ajouter des remotes sans rebuild
  • testez explicitement les rollbacks en changeant la valeur version dans le manifest

Ce que ce PoC vous apporte deja

Ce repository fournit deja les briques principales a reprendre :

  • un shell runtime avec refresh de configuration
  • un mecanisme de detection de changement de version
  • des remotes Angular exposes via ./Routes
  • un repo de configuration externe
  • un package de menu partage
  • un state-bridge optionnel pour les scenarios d'etat transverse

Le principal ecart a implementer dans votre projet cible est la mise en remote de la route /.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors