Microfronts: de quoi parle-t-on?

Toutes ces années, vous, le développeur front-end, avez écrit des monolithes, même si vous avez compris que c'était une mauvaise habitude. Vous avez divisé votre code en composants, utilisé require ou import et défini des packages npm dans package.json ou généré des référentiels git dans votre projet, mais vous avez quand même écrit un monolithe.
Il est temps de changer de position.

Pourquoi votre code peut-il être considéré comme un monolithe?


Par nature, toutes les applications frontales sont monolithiques - à l'exception des applications qui implémentent des micro-frontends. La raison en est que vous développez à l'aide de la bibliothèque React et que deux équipes font le travail. Les deux doivent utiliser la même version de React et se tenir à jour avec les mises à jour, ce qui signifie qu'ils résoudront invariablement les conflits avec la fusion du code. Ils ne sont pas complètement indépendants les uns des autres dans la base de code. Ils utilisent probablement tous le même référentiel et un seul système de génération. Les microservices peuvent économiser des applications monolithiques! Mais comment ça? Après tout, ils sont pour le backend! * surprise incroyable *

Que sont les microservices?


En termes simples, les microservices sont une technique de développement qui permet aux développeurs d'effectuer des livraisons indépendantes de fonctionnalités (versions) pour différentes parties de la plate-forme, et en même temps, les versions ne se cassent pas. Des fournitures indépendantes leur permettent de collecter des services isolés ou faiblement couplés. Il existe plusieurs règles qui rendent cette architecture plus robuste. En bref, ils peuvent être définis comme suit: chaque service doit être petit et effectuer une seule tâche. Par conséquent, l'équipe qui y travaille devrait également être petite. Quelle est la taille d'un projet et d'une équipe, expliquez James Lewis et Martin Fowler:

Les développeurs qui interagissent avec les microservices nomment différentes tailles. Les plus grands d'entre eux répondent à la stratégie de l' équipe de deux pizzas d' Amazon - pas plus de 10-12 personnes. Le pôle inversé - des équipes de 5-6 personnes, où chacune prend en charge un service.

Voici un diagramme expliquant la différence entre un monolithe et des microservices:



Le diagramme montre que chaque service du système de microservices est une application distincte, à l'exception de l'interface utilisateur - il reste un seul ensemble! Lorsque tous les services sont pris en charge par une seule équipe, le risque est grand que, au fur et à mesure de la croissance de l'entreprise, l'équipe frontend ne suive plus l'interface utilisateur. C'est la vulnérabilité de cette architecture.



L'architecture peut entraîner des problèmes d'organisation. Supposons que l'entreprise ait grandi et adopté une méthodologie de développement flexible (je parle d'Agile). Ils nécessitent de petites équipes interfonctionnelles. Bien sûr, dans notre exemple abstrait, les gestionnaires commenceront à séparer les tâches du frontend et du backend, et les équipes interfonctionnelles ne seront pas vraiment interfonctionnelles. Et tous les efforts seront vains: l'équipe peut sembler flexible, mais en fait elle sera très divisée. Gérer une telle équipe n'est pas pour les âmes sensibles. À chaque réunion, il y aura une question: y a-t-il suffisamment de tâches frontales, y a-t-il suffisamment de tâches back-end dans le sprint? Pour résoudre ces problèmes et bien d'autres, il y a quelques années, l'idée du microfront est apparue, qui a rapidement gagné en popularité.

Solution au problème: les microfronts


La solution semble assez évidente, car des principes similaires ont longtemps été appliqués avec succès dans les travaux sur les services backend: diviser un frontend monolithique en petits fragments d'interface utilisateur. Cependant, l'interface utilisateur n'est pas tout à fait similaire aux services - c'est une interface entre l'utilisateur final et le produit, elle doit être réfléchie et systématique. De plus, à l'ère des applications monopages, des applications entières sont lancées via un navigateur côté client. Ce ne sont plus de simples fichiers HTML, ce sont des composants complexes qui peuvent contenir diverses interfaces utilisateur et logique métier. Maintenant, peut-être, il est nécessaire de définir des microfronts.

Le principe des microfronts: la présentation d'un site web ou d'une application web comme un ensemble de fonctions dont les équipes indépendantes sont responsables. Chaque équipe a sa propre mission, son propre domaine de travail sur lequel elle est spécialisée. L'équipe est interfonctionnelle et développe
tout le cycle - de la base de données à l'interface utilisateur ( micro-fontend.org ).

Mon expérience actuelle montre que pour de nombreuses entreprises, il peut être difficile d'accepter l'architecture proposée ci-dessus. Pour d'autres, la charge de l'ancien code ne permet pas la transition vers une nouvelle architecture. Par conséquent, un moyen de migration plus fluide, plus facile et plus fiable est nécessaire. Ayant examiné l'architecture plus en détail, je vais essayer de proposer ma vision pour résoudre le problème. Avant de vous plonger dans les détails, familiarisez-vous avec la terminologie.

Structure générale et quelques terminologies supplémentaires

Imaginez que nous divisions la structure d'une application monolithique verticalement, par fonctions métier. Nous obtiendrons plusieurs applications plus petites avec la même structure que l'application monolithique. Mais si nous ajoutons une application spéciale au-dessus de ces petites applications monolithiques, les utilisateurs interagiront avec elle. À son tour, il intégrera l'interface utilisateur de ces petites applications. Nous appelons ce niveau le lien, car il prend les éléments d'interface utilisateur de chaque microservice et les combine en une seule interface - c'est la mise en œuvre la plus directe du microfront. * admiration sincère *



Pour être plus clair, j'appellerai ci-dessous chaque petite application monolithique une micro- application, car ce ne sont pas seulement des microservices, mais des applications autonomes - chacune a des éléments d'interface utilisateur et chacune représente une fonction commerciale à part entière. Comme vous le savez, l'écosystème frontal d'aujourd'hui est très diversifié et peut être assez complexe. Et ces solutions simples et évidentes peuvent ne pas être appropriées dans le processus de mise en œuvre du produit.

Problèmes à résoudre


Lorsque l'idée de cet article est née, j'ai commencé un sujet sur Reddit pour en discuter. Grâce aux membres de la communauté et à leurs commentaires, je peux lister les problèmes qui doivent être résolus.

Problème numéro 1: obtenir un comportement cohérent et cohérent de l'interface utilisateur lorsque nous avons plusieurs micro-applications complètement autonomes

Il n'y a pas de panacée, mais il y a une idée de créer une bibliothèque d'interface utilisateur commune, qui serait également une micro-application indépendante. Dans ce cas, toutes les autres micro-applications devront dépendre de cette bibliothèque d'interface utilisateur. Et cela tue leur indépendance.

Une autre option consiste à créer des variables CSS communes au niveau racine. L'avantage de cette solution est que nous obtenons un thème personnalisé global pour toutes les applications.

Ou nous pouvons rendre les variables et les impuretés SASS communes à toutes les équipes. L'un des inconvénients de cette approche sera la mise en œuvre répétée d'éléments d'interface utilisateur et la nécessité d'une vérification constante de la conception d'éléments similaires dans toutes les micro-applications.

Problème numéro 2: assurez-vous qu'une équipe ne réécrit pas le CSS d'une autre équipe

Tout d'abord, vous pouvez limiter la portée de CSS en utilisant des sélecteurs formés par le nom de la microapplication. En plaçant cette restriction sur le niveau intermédiaire, vous pouvez réduire le temps de développement global, mais en même temps, la responsabilité du niveau intermédiaire augmentera.

Deuxièmement, vous pouvez faire de chaque micro- application un composant Web personnalisé . L'avantage de cette approche est que le navigateur gère la restriction. Cependant, tout a un prix: avec le Shadow DOM, il est presque impossible de faire un rendu côté serveur. De plus, les éléments personnalisés ne sont pas pris en charge à 100% par les navigateurs , surtout si vous avez besoin de la prise en charge IE.

Problème numéro 3: rendre les informations globales communes aux différentes micro-applications

Ce problème est l'un des plus courants, mais il est résolu assez facilement. HTML5 possède des fonctionnalités assez puissantes, presque inexplorées par la plupart des développeurs front-end.
L'une de ces fonctionnalités est les événements personnalisés qui vous permettent de rendre les informations communes aux micro-applications.

Une implémentation pub-sub ou T39 peut également aider. Si vous avez besoin d'un gestionnaire d'état global plus subtil, vous pouvez implémenter un petit Redux général - cela donne une architecture plus réactive.

Problème numéro 4: si toutes les micro-applications sont autonomes, comment effectuer le routage côté client?

La solution au problème dépend de la mise en œuvre. Tous les principaux frameworks modernes disposent de puissants mécanismes de routage côté client utilisant l'état de l'historique du navigateur. Le problème est de savoir quelle application est responsable de l'itinéraire actuel et quand exactement.

Mon approche pragmatique est de créer un routeur client commun, uniquement responsable des routes de haut niveau, et le reste est à la merci des micro-applications correspondantes. Supposons que nous ayons une définition d'itinéraire /content/:id. Le routeur commun résoudra la partie c /content et l'itinéraire résolu sera transmis à ContentMicroApp. ContentMicroApp est un serveur autonome qui ne sera appelé qu'avec /:id .

Problème numéro 5: avons-nous vraiment besoin de SSR (rendu côté serveur), est-ce possible lors de l'utilisation de microfronts?

Le rendu côté serveur n'est pas facile. Si vous souhaitez regrouper des micro-applications à l'aide d'iframes, oubliez le rendu côté serveur. De même, les composants Web pour la liaison ne sont pas plus forts que les iframes. Cependant, si chacune des micro-applications est capable de restituer du contenu côté serveur, alors la couche de connexion sera uniquement responsable de la combinaison des fragments HTML côté serveur.

Problème 6: «L'intégration avec l'environnement existant est nécessaire comme l'air! Comment le faire? "

Pour l'intégration avec les systèmes existants, je souhaite décrire ma vision, que j'appelle « mise en œuvre progressive ».

Tout d'abord, nous devons implémenter la couche middleware afin qu'elle ait la fonctionnalité d'un serveur proxy transparent. Après cela, nous pouvons définir le système existant comme une microapplication ( LegacyMicroApp ) en lui déclarant une route spéciale. Tout le trafic qui atteint le niveau de connexion sera acheminé de manière transparente vers le système existant, car nous n'avons pas encore d'autres micro-applications.

La prochaine étape est la mise en œuvre progressive. Nous prendrons un petit morceau de LegacyMicroApp , supprimant la navigation principale, la remplaçant par une dépendance. Cette dépendance est une micro-application implémentée à l'aide de la toute nouvelle technologie brillante, NavigationMicroApp.

Désormais, LegacyMicroApp intercepte toutes les routes via la dépendance NavigationMicroApp et les traite en interne.

Ensuite, d'une manière similaire, nous allons refaire le pied de page.

Nous allons donc continuer à mordre un morceau de LegacyMicroApp jusqu'à ce qu'il n'en reste plus rien.

Problème numéro 7: orchestrez le côté client afin de ne pas avoir à recharger la page à chaque fois

La couche middleware résout les problèmes côté client, mais pas côté serveur. Côté client, en téléchargeant un seul HTML, nous ne pouvons pas charger des parties individuelles lors du changement d'URL. Par conséquent, nous avons besoin d'un mécanisme qui charge les fragments de manière asynchrone. Le problème est que ces fragments peuvent avoir des dépendances, et ces dépendances doivent pouvoir être résolues côté client. Cela signifie que la solution microfrontend devrait offrir un mécanisme pour charger les micro-applications et implémenter l'injection de dépendance.

Les problèmes répertoriés ci-dessus peuvent être regroupés dans les rubriques suivantes:

Côté client

  • Orchestration
  • Acheminement
  • Micro isolation
  • Interaction avec l'application
  • Micro-applications Unity UI

Côté serveur

  • Rendu du serveur
  • Acheminement
  • Gestion des dépendances

Architecture flexible et puissante mais simple


Pour cela, cela valait la peine de supporter le début de l'article! Les principaux éléments et exigences de l'architecture microfrontend ont enfin commencé à émerger;)

Guidé par les exigences et les préoccupations, j'ai commencé à développer une solution appelée microfe . * anticipation des retours *
Ici, je décrirai l'architecture du projet, en décrivant brièvement ses principaux composants.

Le moyen le plus simple de démarrer est du côté client, qui a trois structures principales distinctes: AppsManager, Loader, Router , ainsi qu'une autre, MicroAppStore .



AppsManager
AppsManager est au cœur de l'orchestration des micro-applications côté client. L'objectif principal d'AppsManager est de créer une arborescence de dépendances. Une fois toutes les dépendances résolues, AppsManager lance la microapplication.

Chargeur
Un autre élément crucial de l'orchestration côté client est Loader. Il est responsable du téléchargement des applications côté client.

Routeur
Pour effectuer un routage côté client, j'ai implémenté Router en microfe. Contrairement aux routeurs côté client conventionnels, le routeur microfe a des fonctionnalités limitées. Il ne traite pas les pages, mais les micro-applications. Disons que nous avons URL /content/detail/13 et ContentMicroApp. Dans ce cas, le routeur microfe traitera l'URL vers /content/* et appellera la partie ContentMicroApp /detail/13 .

Microapppore
Pour résoudre l'interaction client entre les micro-applications, j'ai implémenté MicroAppStore en microfe. Elle a des fonctionnalités similaires à la bibliothèque Redux, mais avec une mise en garde: elle est plus flexible en ce qui concerne la modification des données asynchrones et la déclaration reducer'a.

***


Le côté serveur est peut-être un peu plus compliqué à implémenter, mais a une structure plus simple. Il se compose de deux parties principales - StitchingServer et MicroAppServer.

Microappserver




La plus petite fonctionnalité possible de MicroAppServer peut être exprimée comme suit: init et serve.
Lorsque MicroAppServer démarre, la première chose à faire est d'appeler SticthingServer et d'enregistrer un point final avec la micro-application annoncée. Il définit les dépendances, les types et les URL du schéma MicroAppServer. Je pense qu'il n'est pas nécessaire de parler de service - il n'y a rien d'intéressant ici.

Serveur de couture




StitchingServer vous permet d'enregistrer un point de terminaison auprès de MicroAppServers. Lorsque MicroAppServer s'enregistre auprès de StichingServer, StichingServer enregistre la déclaration MicroAppServer.

Plus tard, StitchingServer utilise l'annonce pour résoudre MicroAppServices à partir de l'URL demandée.

Après avoir autorisé MicroAppServer et toutes ses dépendances, l'URL publique correspondante apparaîtra dans les noms de tous les chemins correspondants en CSS, JS et HTML. Une étape supplémentaire consiste à ajouter un préfixe MicroAppServer unique aux sélecteurs CSS pour éviter les conflits entre les micro-applications côté client.

Ensuite, la tâche principale de StitchingServer entre en scène: assembler toutes les pièces reçues et renvoyer la page HTML entière.

Quelques mots sur les autres implémentations


Même avant l'apparition du terme microfrontend en 2016, de nombreuses grandes entreprises ont essayé de résoudre des problèmes similaires - par exemple, Facebook avec son BigPipe .
Maintenant, l'idée prend de l'ampleur. Les entreprises de toutes tailles sont intéressées par ce sujet, y investissant temps et argent. Par exemple, Zalando a fourni le code open source de sa solution Project Mosaic . Je peux dire que microfe et Project Mosaic suivent des approches similaires, mais avec quelques différences cardinales. Si la microfe recourt à un routage entièrement décentralisé pour rendre chaque micro-application plus indépendante, Project Mosaic préfère un routage centralisé et une définition de modèle pour chaque route. Soit dit en passant, Project Mosaic facilite la réalisation de tests AB et la génération de modèles dynamiques à la volée.

Il existe d'autres approches, en particulier, en utilisant les iframs comme couche de connexion - évidemment, pas du côté serveur, mais du côté client. Il s'agit d'une solution très simple qui ne nécessite pas de structure de serveur spéciale ni d'implication de DevOps. Il peut être mis en œuvre par l'équipe front-end de manière indépendante, ce qui signifie qu'il crée moins de problèmes d'organisation pour l'entreprise et coûte moins cher.

Il existe toujours un cadre de spa unique . Le projet s'appuie sur des conventions de dénomination pour chaque application afin d'autoriser et de télécharger des micro-applications. Facile à saisir l'idée et à suivre les modèles. Le cadre peut donc être utile pour se familiariser avec le système et l'expérimenter dans votre environnement local. L'inconvénient du projet est que vous devez créer chaque micro-application d'une manière strictement définie - sinon, le cadre pourrait ne pas l'accepter.

Conclusion (et liens)


Je pense qu'avec le temps, le sujet des microfronts sera examiné plus en détail. S'il commence à attirer l'attention de plus en plus d'entreprises, ce concept deviendra la méthode de développement par défaut dans les grandes équipes. Il sera utile pour chaque développeur frontal de se familiariser avec cette architecture dans un proche avenir et d'acquérir une expérience précieuse en travaillant avec elle.

serveur de registre d'application micro fe
micro infrastructure frontale

Source: https://habr.com/ru/post/fr459540/


All Articles