Dans le monde numérique en évolution rapide d'aujourd'hui, où l'agilité et l'évolutivité sont cruciales, les entreprises recherchent constamment des moyens d'améliorer les performances et la maintenabilité de leurs applications Web.
Une approche populaire pour atteindre ces objectifs consiste à migrer d'une architecture monolithique vers une architecture distribuée (ou micro-frontend). Cette série d'articles, "Micro-frontend Migration Journey", partage mon expérience personnelle d'entreprendre une telle migration pendant mon séjour chez AWS.
AVIS DE NON-RESPONSABILITÉ : Avant de commencer, il est important de noter que même si cet article partage mon expérience personnelle, je ne suis pas en mesure de divulguer des détails propriétaires ou internes sur des outils, des technologies ou des processus spécifiques chez AWS ou toute autre organisation.
Je m'engage à respecter les obligations légales et à veiller à ce que cet article se concentre uniquement sur les concepts généraux et les stratégies impliqués dans le parcours de migration micro-frontend.
Le but est de fournir des idées et des leçons apprises qui peuvent être applicables dans un contexte plus large, sans divulguer aucune information confidentielle.
J'ai découvert les micro-interfaces (je suppose que beaucoup d'entre vous) grâce à l' article sur le blog de Martin Fowler. Il a présenté différentes manières de composer une architecture micro-frontend de manière indépendante du framework.
En approfondissant le sujet, j'ai réalisé que notre architecture monolithique existante devenait un goulot d'étranglement important pour la productivité de notre équipe et entravait les performances globales de notre application.
L'un des principaux facteurs qui m'a poussé à envisager une migration était la taille croissante du bundle de notre application.
Après avoir effectué une analyse approfondie du bundle à l'été 2020, j'ai découvert que depuis son lancement initial au début de 2019, la taille du bundle (gzippé) était passée de 450 Ko à 800 Ko (il fait presque 4 Mo analysés) - soit près du double de la taille d'origine.
Compte tenu du succès de notre service et de la prévision de sa croissance continue, il était clair que cette tendance persisterait, impactant davantage les performances et la maintenabilité de notre application.
Bien que j'étais enthousiasmé par le concept de micro-interfaces, j'ai également reconnu que nous n'étions pas encore prêts à les adopter en raison des défis spécifiques auxquels nous étions confrontés :
Petite structure organisationnelle : Au moment de mon analyse, notre organisation était relativement petite et j'étais le seul ingénieur frontend à plein temps de l'équipe. La migration vers une architecture micro-frontend a nécessité un investissement important en termes de structure organisationnelle et de fondation opérationnelle.
Il était crucial d'avoir une structure mature capable de gérer efficacement l'architecture distribuée et de refléter les dépendances entre les différents composants frontaux.
Domaine d'activité limité : bien que les micro-frontends puissent être divisés en fonction de contextes limités et de capacités commerciales (en savoir plus dans l'article " Conception axée sur le domaine dans l'architecture micro-frontend" ), notre domaine d'activité principal n'était pas assez étendu pour justifier un découplage complet en plusieurs micro-interfaces. Cependant, il y avait des limites visibles au sein de l'application qu'il était logique de découper et de passer à une architecture distribuée.
Compte tenu de ces facteurs, j'ai réalisé qu'une approche graduelle était nécessaire. Plutôt qu'une migration complète vers des micro-frontends, j'ai cherché à identifier des domaines spécifiques au sein de notre application qui pourraient bénéficier d'une architecture distribuée.
Cela nous permettrait de répondre aux problèmes de performance et d'évolutivité sans perturber la structure organisationnelle globale ni compromettre l'intégrité de notre domaine d'activité. Cela nous donnerait également du temps pour développer l'équipe et observer les orientations commerciales.
Veuillez noter que si vous souhaitez résoudre le problème de performances de l'application (taille de l'ensemble) uniquement via l'architecture mciro-frontend, ce n'est peut-être pas la meilleure idée. Il serait préférable de commencer par une architecture monolithique distribuée qui tirera plutôt parti du chargement paresseux (importations dynamiques).
De plus, je pense qu'il gérerait les problèmes de taille de bundle plus gracieusement que l'architecture micro-frontend étant donné que l'architecture micro-frontend est très susceptible d'avoir du code partagé qui ne serait pas séparé en morceaux de fournisseur, et il serait intégré dans le bundle d'applications ( c'est l'un des inconvénients d'une telle architecture distribuée - vous devez avoir un compromis entre ce qu'il faut partager, quand et comment).
Cependant, l'architecture monolithique distribuée n'évoluera pas aussi bien que le micro-frontend. Lorsque votre organisation se développe rapidement, votre équipe se développera probablement au même rythme également.
Il serait essentiel de diviser la base de code en différents domaines de propriété contrôlés par différentes équipes.
Et chaque équipe devra avoir ses propres cycles de publication indépendants des autres, chaque équipe appréciera si sa base de code se concentre uniquement sur son domaine, et construira rapidement (isolation du code -> meilleure maintenabilité/moins de code à maintenir et build -> meilleure testabilité/moins de tests à maintenir et à exécuter).
Pour obtenir le soutien de la direction, j'ai élaboré un document de vision technique convaincant qui englobait une analyse complète des performances, y compris des mesures vitales pour le Web, et décrivait les différentes phases de la migration vers des interfaces distribuées.
L'une des phases intermédiaires de cette migration consistait à établir une architecture monolithique distribuée, dans laquelle plusieurs modules/widgets pouvaient être livrés de manière asynchrone via des techniques de chargement différé tout en tirant parti d'une infrastructure partagée, telle qu'un compartiment S3 et un CDN, entre le service principal et les widgets. .
Comme je l'évoquais dans mon article précédent, l'idée principale de ce type de document est de décrire l'avenir tel que vous voudriez qu'il soit une fois les objectifs atteints et les plus gros problèmes résolus. Il ne s'agit pas du plan d'exécution !
Presque 1 an plus tard, le moment était enfin venu de mettre en œuvre mon plan de migration micro-frontend. Avec l'expansion imminente dans un nouveau domaine et une équipe plus importante à notre disposition, nous étions bien équipés pour exécuter la migration.
C'était comme une occasion en or que nous ne pouvions pas nous permettre de manquer.
Après tout, rester confiné à l'architecture monolithique reviendrait à se débattre perpétuellement avec ses limites.
Le délai limité pour se développer dans un nouveau domaine a servi de catalyseur, nous propulsant vers la construction immédiate d'une architecture plus évolutive et maintenable au lieu d'avoir des itérations courtes et lentes !
Pour exécuter la migration et gérer simultanément le travail dans le nouveau domaine, nous avons divisé les équipes en deux groupes dédiés. Le travail sur les fonctionnalités, qui avait une priorité plus élevée, nécessitait plus de ressources et devait itérer à un rythme plus rapide.
Pour garantir l'intégrité et la compréhension globale du processus de migration, il était logique d'affecter une petite équipe dédiée spécifiquement responsable de la gestion de la migration.
Cependant, nous ne pouvions pas poursuivre le travail sur les fonctionnalités sans nous assurer au préalable que le concept de micro-frontend serait un succès.
Pour atténuer les risques et fournir une feuille de route claire, il était essentiel de créer un document de conception de bas niveau comprenant des estimations précises et une évaluation approfondie des risques. Ce document a servi de modèle, décrivant les étapes et les considérations nécessaires pour la migration.
L'étape cruciale de ce processus a été le développement d'une preuve de concept qui démontrerait l'intégration réussie de tous les composants conformément à la conception.
Ce jalon, nommé à juste titre le "Point de non-retour", visait à valider la faisabilité et l'efficacité de l'architecture micro-frontend.
Alors que j'étais optimiste quant au succès de la migration, il était essentiel de se préparer aux imprévus. Par conséquent, j'ai conçu un plan B, qui a agi comme une stratégie de secours au cas où le concept initial ne donnerait pas les résultats souhaités.
Cela incluait l'allocation de sept jours supplémentaires dans les estimations spécifiquement pour me faire pleurer dans l'oreiller plus quelques jours pour avoir une nouvelle entrée de module de fonctionnalité connectée au noyau via un chargement paresseux (vous vous souvenez du monolithe distribué ?).
Lors de la conception de micro-interfaces, il existe généralement 3 approches pour la composition, chacune se concentrant sur l'endroit où la résolution de l'application d'exécution a lieu. La beauté de ces approches est qu'elles ne sont pas mutuellement exclusives et peuvent être combinées selon les besoins.
L'idée de base est de tirer parti d'un serveur proxy inverse pour diviser les bundles micro-frontend par page et effectuer un rechargement de page dur en fonction de l'URL de la route.
Avantages:
Les inconvénients:
L'état global ne sera pas synchronisé entre les applications micro-frontend. C'était clairement un point interdit pour nous car nous avions des opérations d'arrière-plan de longue durée effectuées côté client.
Vous pourriez dire que nous pourrions conserver un instantané de la "file d'attente" de cette opération sur le stockage local et le lire après un rechargement dur, mais pour des raisons de sécurité, nous n'avons pas été en mesure de l'implémenter.
Ceci n'est qu'un exemple d'état global, mais voici un autre exemple de ce à quoi il peut ressembler : état des panneaux de navigation latéral (développé/réduit), messages toast, etc.
Une autre approche de la composition micro-frontend est la composition côté bord, qui consiste à combiner des micro-frontends au niveau de la couche périphérique, comme un CDN. Par exemple, Amazon CloudFront prend en charge l'intégration Lambda@Edge , permettant l'utilisation d'un CDN partagé pour lire et servir le contenu micro-frontend.
Avantages:
Les inconvénients:
La composition côté client est une autre approche de l'architecture micro-frontend qui utilise des techniques d'orchestration de micro-frontend côté client, découplées de l'implémentation du serveur.
L'acteur clé de cette architecture est une application conteneur (shell) qui a les responsabilités suivantes :
L'idée générale est que chaque bundle micro-frontend produirait 2 types de fichiers de ressources :
{hash}/index.js : cela sert de point d'entrée pour l'application micro-frontend, le hachage représentant un identifiant unique pour l'ensemble de la construction.
Le hachage agit comme une clé de préfixe pour chaque bundle dans le compartiment S3. Il est important de noter que plusieurs points d'entrée peuvent exister, mais le hachage reste le même pour chacun d'eux.
manifest.json : il s'agit d'un fichier manifeste qui contient les chemins d'accès à tous les points d'entrée de l'application micro-frontend. Ce fichier resterait toujours à la racine du compartiment S3, afin que le conteneur puisse le découvrir facilement.
Je recommande d'activer la gestion des versions de ce fichier dans le compartiment S3 afin d'avoir une meilleure observabilité des modifications. Si vous utilisez Webpack pour construire votre projet, je recommande fortement WebpackManifestPlugin qui fait tout le gros du travail pour vous.
Le conteneur ne connaît que l'URL du domaine source de l'actif micro-frontend (origine CDN) en fonction de l'étape et de la région. Lors du chargement initial de la page, le conteneur télécharge le fichier manifeste pour chaque application micro-frontend.
Le fichier manifeste est de petite taille (~ 100 octets) pour éviter d'avoir un impact sur le temps de chargement de la page et s'adapte bien même lors de l'agrégation de plusieurs micro-interfaces dans un conteneur. Il est crucial de considérer le fichier manifeste comme immuable dans le stockage de cache du navigateur pour éviter une mise en cache agressive.
Choisir la bonne bibliothèque d'orchestration est le plus grand défi dans cette composition et sera discuté dans le chapitre suivant.
Avantages:
Les inconvénients:
Comme je l'ai mentionné plus tôt dans ce chapitre, tous ces modèles de composition peuvent être mélangés et assortis dans la même application shell. Voici un exemple de ce à quoi cela peut ressembler :
Je recommande de commencer par une approche homogène au début - sélectionnez un modèle de composition qui vous convient le mieux et commencez à construire l'infrastructure qui l'entoure.
Pour nous, la composition côté client était la meilleure option, mais pour l'avenir, nous avons envisagé de passer certaines régions à l'orchestration côté périphérie (en fonction de la disponibilité de Lambda@Edge).
Lorsqu'il s'agit d'implémenter la composition côté client dans une architecture micro-frontend, la sélection de la bonne bibliothèque d'orchestration est une décision critique.
La bibliothèque choisie jouera un rôle crucial dans la gestion du chargement dynamique et de la coordination des micro-interfaces au sein de l'application conteneur.
Plusieurs bibliothèques d'orchestration populaires existent, chacune avec ses propres forces et considérations.
Single-spa est une bibliothèque d'orchestration largement adoptée qui offre une approche flexible et extensible de la composition micro-frontend. Il permet aux développeurs de créer une application shell qui orchestre le chargement et le déchargement de plusieurs micro-interfaces.
Single-SPA offre un contrôle précis des événements du cycle de vie et prend en charge différents cadres et technologies.
Avantages:
Les inconvénients:
Qiankun est une puissante bibliothèque d'orchestration développée par l'équipe Ant Financial (Alibaba). Il utilise une approche HTML partielle pour la composition. Du côté de l'application micro-frontend, il produit un extrait HTML simple avec tous les points d'entrée à charger.
Après avoir consommé ce fichier HTML, le conteneur effectue toute l'orchestration et monte l'application. Dans cette configuration, le HTML partiel joue le rôle d'un fichier manifeste dont j'ai parlé dans le chapitre précédent.
Avantages:
Les inconvénients:
La fédération de modules , une fonctionnalité fournie par Webpack, a attiré l'attention et le battage médiatique dans la communauté des développeurs Web. Cette technologie permet aux développeurs de partager du code entre plusieurs applications lors de l'exécution, ce qui en fait une option attrayante pour la création de micro-interfaces.
Grâce à son intégration transparente avec Webpack et à sa flexibilité d'exécution, Module Federation est devenu un choix populaire pour la gestion et l'orchestration des micro-interfaces.
Avantages:
Les inconvénients:
Dans cette première partie de la série "Micro-frontend Migration Journey", nous avons discuté de la motivation derrière la migration d'un monolithe Web vers une architecture distribuée et des premières mesures prises pour vendre l'idée à la direction.
Nous avons exploré l'importance d'un document de vision technique qui présentait une analyse détaillée des performances et décrivait les différentes phases de la migration.
Nous nous sommes ensuite penchés sur les considérations de conception pour les micro-frontends, en discutant de trois approches : la composition côté serveur, la composition côté périphérie et la composition côté client.
Chaque approche a ses avantages et ses inconvénients, et le choix dépend de divers facteurs tels que la synchronisation de l'état global, l'expérience client, la complexité de l'infrastructure et la mise en cache.
En outre, nous avons exploré les bibliothèques d'orchestration populaires, telles que single-spa, qiankun et Module Federation, en mettant en évidence leurs fonctionnalités, leurs avantages et leurs défis potentiels.
Rejoignez-moi dans les prochaines parties de la série alors que nous poursuivons notre voyage de migration micro-frontend, découvrant des informations plus intéressantes et précieuses en cours de route !
Publié à l'origine sur https://thesametech.com le 18 avril 2023.
Vous pouvez aussi me suivre sur Twitter , et vous connecter sur LinkedIn pour être notifié des nouveaux posts !