Donnez un Microfrontend à vos Microservices

Breaking the monolith

Yann L
Photo by James Traf on Unsplash

Introduction

Les infrastructures Microservices sont le fruit d’un constat simple : les applications monolithes sont difficiles à gérer, maintenir ou moderniser. Il fallait donc trouver un moyen de réduire la codebase en petit sîlots qui seraient plus simples à faire évoluer.

Cette solution trouvée pour la structure “back”, il nous reste toujours la problématique du web front où nous avons une SPA qui est en fait un monolithe en soit. La gestion de modules, le lazy-loading, etc. nous permettent d’améliorer la structure, mais la codebase reste commune. Il nous faut donc maintenant splitter cela et ainsi créer des micro-frontends.

TL; DR;

Les architecture backend se sont orientés vers les microservices afin de mieux découper les codebases en petites briques indépendantes et ainsi améliorer la maintenabilité.

L’architecture frontend suit ce trend afin également de mieux se structurer et permettre une meilleure réutilisation de modules indépendants au sein d’applications. Ce splitting permet également à une équipe de gérer les composants de son domaine sur toutes les couches (DB-Microservice-Front) afin de les faires évoluer ensembles et de maitriser le domaine complet. Les développeurs d’applications pourront eux se focaliser sur leur application et non sur l’intégration avec l’architecture de donnée IT existante.

Dans ce but, plusieurs solutions sont possibles, mais un rapide comparatif nous montre qu’actuellement les plus efficaces autant au niveau technique qu’au niveau rendu utilisateur, sont l’utilisation des technologies WebComponents. Ceci, que ce soit directement avec la création de WebComponents ou via des Framework based components.

Photo by rawpixel on Unsplash

Du monolithe aux microservices

On le sait tous, les applications à l’ancienne se faisait au moyen de monolithe qui à la base était une app (data-layer + logique + présentation) pour un domaine précis, puis au fur et à mesure grandissait jusqu’à devenir une codebase qui contient tout plein de choses (ex: SAP, SIRH …).

Pour mieux découper ces codebases et faciliter la maintenance, le back s’est petit à petit divisé en structures indépendantes, jusqu’à devenir des microservices. Le but de cet exemple microservice n’est pas d’expliquer cette transformation déjà connue, mais juste de montrer les similitudes avec ce que les technologies frontend tentent de faire et vers quoi elles veulent aller.

Du monolithe aux microservices

Step 1 : Le monolithe

Tout est dans la même solution. On retrouve notre business logique dans la même codebase que le data access et les pages du UI frontend. Une modification d’une couche nécessite un déploiement de toute la solution.

Step 2 : La séparation Back-Front

Avec l’arrivée des XHR (xml http requests), le frontend se sépare et devient un élément à lui seul. La partie backend, elle, garde ses multiples couches.

Step 3 : Les Microservices

Le splitting en architecture microservice permet d’isoler les domaines, et ainsi de splitter les responsabilités des équipes de développement. Le backend applicatif se transforme en un Back For Front (BFF) qui est l’API de communication dédiée au frontend. L’API gateway peut parfois se substituer à ce BFF ou dans certains cas s’ajouter à celui-ci.

On a juste réglé le problème du back…

Quand on voit la découpe qui s’est faite avec le temps, on peut facilement se dire que problème du monolithe a été réglé en partie. On a à présent une bonne découpe du back avec une séparation des domaines par API, mais on a toujours une grosse app front qui fait tout (login, gestion du client, de ses contrats, …). Celle-ci grossit également avec chaque nouvelle feature, nouveau domaine ajouté, …

Avec cela, viennent les problèmes techniques :

  • une application de plus en plus grande à déployer (hausse du risque)
  • de plus en plus de code à maintenir (et donc difficulté de migrations évolutives vers des nouvelles technologies)
  • difficulté de recruter des personnes compétentes sur une stack qui vieillit

Du monolithe aux microfrontends

Tout comme pour le back, il fallait donc trouver une solution pour éviter le fourre-tout. Il nous fallait un moyen de découper une application frontend en domaines indépendants et réutilisables et les intégrer dans les différentes applications.

Pour permettre cela, les développeurs se sont orientés vers la componentization. Chaque composant a ainsi une responsabilité qui lui est propre, et qui pourrait être utilisé dans différents contextes. Elle ne nécessiterait qu’un seul développement qui devrait représenter le domaine ciblé (et donc indirectement l’API ciblée). Chaque client intéressé pourrait ensuite reprendre ces fragments et les intégrer dans son application selon les besoins de ses utilisateurs finaux.

Du monolithe aux microfrontends

Au niveau UI on arriverait donc à quelque chose comme cela. Chaque microfrontend est une intégration de composants partagés et gérant une feature applicative spécifique (ex: un business domain comme la recherche du client ou un technical domain comme une gestion de single sign-on).

Microfrontend based application

L’équipe en charge du microservice peut donc également créer un composant web qui représente le service. Les développeurs d’applications frontend n’auront eux plus besoin de connaître sur le bout des doigts le domaine du microservice. Ils n’auront qu’a intégrer le composant créé par l’équipe microservice.

Lorsque le microservice évoluera, le composant adapté sera développé en même temps par la même équipe (mais probablement des experts techniques différents) et sera ainsi prêt à être intégré rapidement par toutes les applications clients.

Quels sont les avantages et inconvéniants ?

Cette stratégie soulage les équipes de développements en bout de chaîne qui avaient besoin de trop de connaissances métiers pour une application de gestion. Ils devaient connaitre les contenus, contraintes, validations, structure, etc. de chaque microservice qu’ils implémentent.

Au lieu de ça, nous avons à présent des équipes en silot qui doivent connaitre uniquement leur domaine métier. Comme dans tous les domaines, être moins généraliste permet ainsi d’être plus spécialisé et plus performant dans un domaine précis. Les équipes applicatives en bout de chaîne pourront se focaliser sur le but final de leur application et non sur l’intégration avec les différents microservices de l’architecture IT.

Le désavantage par contre sera que chaque équipe devra avoir une connaissance technique plus élargie car il y’a fort a parier que le language ne sera pas le même pour le front et le back. On réduit ainsi le scope métier mais tout en agrandissant le scope technique de l’équipe. Au final cela devrait quand même être positif car nous (IT) sommes des techniciens et notre force n’est pas dans les connaissances business. Nous pouvons donc livrer des composants et services de qualités dans un domaine fonctionnel réduit.


Concrêtement, avec des technologies web actuelles

En Web moderne, il y’a plusieurs moyens de le faire et tous ont leurs avantages et inconvénients. Le choix dépendra avant tout du besoin et malheureusement souvent du triangle budget-coût-délai. Ce sera donc à nous, techniciens, de faire le bon choix et de le vendre.

Ces solutions se découpent en 2 catégories distinctes :

  • Separate runtime solutions
  • Shared runtime solutions

De nos jours, les besoins et tendances nous guident le plus souvent vers les shared runtime solutions qui permettent la meilleure qualité autant pour l’utilisateur final que pour les développeurs.

Separate runtime solutions

Les solutions separate runtime sont des applications indépendantes les unes des autres et qui possèdent donc des ressources dédiées (sous-entendu: process d’exécution).

Les microfrontend apparaitront comme une même application pour une vision utilisateur, mais au niveau technique, la séparation et bien présente.

Les iframe

Description

Les iframes sont un concept plutôt bien répandu et permettent d’intégrer une page web (www.webpage1.org) dans une autre (www.webpage2.org). Les barrières techniques sont ainsi les mêmes que si les deux pages étaient dans des onglets différents, mais visuellement pour l’utilisateur elles sont 1 seule et même page.

Avantages

  • Plusieurs différentes pages/vues sur la même page

Inconvénients

  • Gestion des CORS
  • Communication inter-iframe limitée au messaging
  • Web techno (old) qui ne satisfait pas le mobile dev.
  • L’intégration d’une page entière dans une autre péjore bien souvent l’UX
  • Difficulté de gestion de version en cas d’interaction entre la page container et la page embedded. La modif dans l’une nécessite une modif syncronisée dans l’autre.

Conclusion

Les iframes sont un concept vieillissant du web qui répondait à des besoins de l’époque du web peu interactif. Aujourd’hui elles sont de plus en plus abandonnées au profit de nouvelles technologies. L’intégration finale est souvent mauvaise au niveau UX et c’est donc plutôt de simple extraits statiques qui sont présentés sous cette forme, sans réel besoin d’interaction entre les deux pages.

Micro apps

Description

L’application utilise le routing applicatif pour accéder à d’autre micro-frontend. Le but ici est de garder des applications distinctes par business domain, mais avec la possibilité de les chainer en utilisant des hyperliens ou des redirections.

Ex:

  • 1 application = Customer
  • 1 application = Contract
  • 1 application = Payment
  • 1 application “homepage” qui propose à l’utilisateur des liens vers ces différents domaines afin qu’il puisse lui-même choisir ses étapes

Avantages

  • Bonne découpe technique par domaine (chaque dev-team gère uniquement son business domain et ses spécificités)
  • Facilité de gestion et déploiement au niveau IT

Inconvénients

  • Nécessite une bonne gestion de transfert d’identité (application shared login, single sign-on, token, …)
  • Nécessite d’avoir tout le business domain identifiable à partir de paramètre d’URL
  • Nécessite une division très distincte des business domains dans l’application
  • Chaque changement dans le routing d’un domain devra être répliqué dans toutes les app l’intégrant.
  • L’application d’un domaine doit connaitre tous les autres domaines liés afin de proposer des liens vers ceux-ci et permettre un workflow (ou alors c’est un backend qui fournit ces liens, mais on risque d’entrer rapidement dans un mode qui a déjà montré ses limites lorsque l’on veut piloter un front depuis le back).
  • Le workflow est difficilement restrictible. On donne un accès à tout, de partout. Difficile de cadrer l’utilisateur en lui disant : step 1 tu fais ça, step 2 tu fais ci, step 3… et donc il faut que l’utilisateur connaisse bien son domaine applicatif sans besoin d’être guidé/cadré.

Conclusion

Même si cette solution apporte une bonne découpe des domains au niveau SI elle n’est de loin pas parfaite, et c’est surtout l’utilisateur final qui pâtira de cette solution et qui risque de vous détester (bad UX)…


Shared runtime solutions

Avec Shared runtime solutions, on designe des applications qui tournent dans le même processus et partagent ainsi leurs ressources. Les composants peuvent venir de plusieurs horizons différents, mais leur intégration se fait au sein de la même application et à part entière de celle-ci. Autant au niveau technique que utilisateur, l’application est une seule et unique application.

Web components

Description

Les composants web sont des composants en HTML/JS/CSS créés sous forme de librairies et pouvant être implémentés et réutilisés dans des applications.

Similaire aux éléments natifs du HTML (<div>, <input>, <button>,...) ils peuvent être créés, puis enregistré dans la librairie de composants (custom-element) du moteur de rendu. Ils pourront ensuite être utilisé par une balise selon le nom personnalisé choisi (ex: <shopping-cart></shopping-cart>).

Avantages

  • Standard W3C en pleine expansion
  • Encapsulation JS et CSS (shadow Dom)
  • Interaction simple et standard via les events
  • Mobile ready
  • Chaque composant est déployable de manière indépendante
  • Plusieurs versions de composants peuvent être utilisés en parallèle
  • Les composants/modules sont indépendants, mais peuvent communiquer via events avec la base app pour coordination inter-composants.
  • Permet de scoper les styles et/ou de les surcharger afin d’assurer une ligne graphique continue avec la base app.

Inconvénients

  • Les différentes version d’implémentation (ex: shadowDom v0, shadowDom v1) dans les browsers et le recours aux polyfills
  • Component responsiveness. La libre intégration du webcomponent nécessitera d’utiliser du JS pour faire du responsive design selon le container parent et non via le CSS (media width).
  • Les web components devraient être lightweight et donc ne pas être basé sur un framework. Si la complexité nécessite un framework soit les responsabilités sont trop nombreuses, soit c’est un module et il vaut mieux passer au “Framework based components”.

Conclusion

La meilleure façon d’intégrer des composants custom qui ne sont pas trop complexes ou lourds. On ciblera plutôt des petites features réutilisables et dont la logique peut-être blackboxée à l’intérieur.

Framework based components

Description

On créé des composants plus complexes (modules) que ce qu’on ferait avec un webcomponent. On peut ainsi se baser sur React, Angular,… afin de nous simplifier les développements et intégrer des fonctionnalités avancées tels que des appels de services, de la logique métier,…

Ex:

  • 1 module gestion de client (UI + xhr et logique si nécessaire)
  • 1 module gestion de contrat (UI + xhr et logique si nécessaire)
  • 1 app qui intègre ces modules et qui correspond à un flux précis (ex: ouverture de sinistre, offre et conclusion, …)

Avantages / Inconvénients

Framework based components implique la technologie WebComponent. Les avantages/inconvénients cité dans le chapitre WebComponents seront donc applicables ici.

Avantages

  • Permet de faire des composants complexes (modules) réutilisables dans différents contextes (business domain)
  • Chaque dev-team peut s’occuper de son business domain du back au front (création de service et de composants liés pour être implémentés dans les différentes app)
  • UX to its best (liberté de design de flux applicatif par la base app, selon les besoins des user.)

Inconvénients

  • Mieux vaut choisir un unique framework au sein des différentes teams pour standardiser et éviter de charger l’app avec plusieurs librairies et framework. Ca permet aussi d’éviter d’utiliser des outils comme http://single-spa.surge.sh
  • La montée de version des apps et des composants devra être faite périodiquement afin d’éviter des différences entre les versions de framework de l’app et de celles des composants (sinon, ça passe ou ça casse).

Conclusion

A noter que les frameworks modernes utilisent les technologies webcomponents. Le fait de faire du Framework based components implique donc de faire du WebComponent mais avec cette dernière complexité gérée par le framework lui-même.

Pour le partage de composants complexes, c’est la solution la plus efficace que ce soit au niveau développement comme au niveau UX. On peut ainsi intégrer de manière transparente pour l’utilisateur différents modules et gérer des workflows afin de le cadrer dans ses tâches.

Cette solution nécessitera très certainement un application state géré par la base app, afin d’orchestrer et synchroniser tous les composants.

Transclusion

Description

L’application est faite de plusieurs sous-applications et est rendue en tant qu’une seule et même application. Ce merge de microfrontend peut se faire soit server-side, soit client-side. Pour cela on utilise des Edge Side Includes (ESI) qui sont en fait des balises d’inclusion propres au langage.

Ex:

  • Server-side : Pour PHP on connait par exemple include
  • Client-side : En Javascript on récupère via Ajax les microfrontends qu’on aimerait inclure. Ceux-ci sont transmis sous forme de page web. Des librairies comme h-include.js peuvent ensuite nous mâcher le travail pour l'intégration dans la base app.

Avantages

  • Les composants sont intégrés à l’application

Inconvénients

  • Les performances sont péjorées
  • Au niveau serveurs il n’y a pas de moteur de transclusion. C’est le language qui s’occupe de faire ce boulot et donc il faut une uniformité dans les technologies utilisées pour les composants.

Conclusion

Les framework based components et webcomponents sont en fait une forme de transclusion. La différence de la transclusion comme expliquée ici est qu’elle va chercher ses dépendances au moment de l’appel et donc que le temps nécessaire pour afficher la page final à l’utilisateur est prolongé. Pour ces raisons on préferera les méthodes via composants.

Yann L

Written by

Yann L

Passionate frontend engineer who learns a lot on the Internet. I try to share my knowledge when I have the time.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade