Micro-frontends : Comment les intégrer ?

Eric DARIELEric DARIEL
11 min read

Ceci est la seconde partie sur les micro-frontends (il y a tant à dire sur le sujet).
Cette fois-ci, je vais vous parler de l’intégration de ces micro-frontends (ou MFE).
Sur un micro-service, il est simple d’exposer plusieurs versions. Les clients peuvent facilement appeler la V1 ou la V2 d’un même micro-service, finalement c’est le front qui va décider sa version souhaitée du back.
Pour les MFE par contre, on ne va pas demander à l’internaute de changer de version manuellement dans son url en demandant la V2, il serait intéressant d’avoir un moyen de pouvoir configurer, déplacer, supprimer, tester un MFE en temps réel sans besoin de redéployer.

C’est là que Liferay entre en scène, comme je l’avais déjà évoqué dans la conclusion de mon dernier article.

1 - Liferay et les micro-frontends

Liferay est un outils en constante évolution depuis le début des années 2000.
Il existe en version CE (gratuite) et DXP (payante avec un support) et toutes les sources sont disponibles sur GitHub, il est donc très simple de voir ce qui a été fait, comment ça a été fait et le faire évoluer, car Liferay repose sur OSGi (principe micro-services) et est désormais en Java 21.
Voici un schéma d’architecture résumant bien le fonctionnement de Liferay :

Liferay au fil des années est passé d’un monolithe à désormais 1390 modules en version CE. Modules qu’il sera facile de désactiver, supprimer, blacklister, surcharger… et bien sûr en créer de nouveaux.
Historiquement, Liferay gérait des widgets (ou portlets) et a toujours offert la possibilité de les déplacer, supprimer, configurer en temps réel ou bien en avance de phase.
Tout ce savoir faire a évolué en version 7.x, avec l’arrivée des fragments :

Un fragment c’est un composant réutilisable et modifiable à chaud qui contient une partie HTML, une partie CSS, une partie JS et enfin une partie configuration, le tout est exécuté en temps réel, un peu comme un CodePen ou un Jsfiddle.

En version 7.3, ces fragments ont encore été améliorés. On peut désormais :

  • les dupliquer,

  • les déplacer,

  • les exporter,

  • les importer,

  • les composer,

  • les configurer,

  • faire des brouillons,

  • les créer en live

Et en version 7.4, a été ajouté le principe de Client Extension (ou CX). Ces Clients eXtensions permettent de définir des extensions clientes externes que l’on va pouvoir déployer sur son instance Liferay.
Désormais, Liferay propose une version “online” dite SaaS, même si il est toujours possible de faire du PaaS, ou bien d’héberger son Liferay soi-même (sur son PC, son serveur ou son Kubernetes en mode “Self-Hosted”).
L’avantage des CX est qu’ils ne sont pas intrusifs, il est possible de les déclarer via les IHMs (ou le code) avec l’idée de déporter le code en dehors de Liferay.
Liferay est donc plus facile à upgrader/migrer car le code ajouté sera constitué de ressources externes hébergées ailleurs avec leur propre cycle de vie.
De plus, Liferay a décider de ne plus changer de version majeure, la 7.4 devrait être la dernière et désormais les mises à jour se font simplement module par module.

2 - Intégrer des “Objects”

Comme je l’ai évoqué dans mon précédent article, Liferay propose du LowCode/NoCode avec les Liferay “Objects” qui sont exposés en REST et GraphQL.

Dans cet écran, on voit que j’ai déclaré un “Object” Contrat qui va contenir un libellé, une date de début, une date de fin…
Et les entrées de cet “Object” pourront être visualisés, créés, modifiés, supprimés en temps réel au moyen de widgets fournis par Liferay mais seront aussi disponibles sous forme de collections et accessibles en “headless” comme le montre l'écran suivant accessible via l’url de l’API Explorer :

Finalement pour le backend, plus besoin de s'embêter, Liferay stocke les données en base de données et les indexe dans l’ElasticSearch donc aucun soucis de performance ou de limite, toutes les données sont triables, paginables et recherchables nativement.

3 - Intégrer des “Custom Elements”

Concernant la partie frontend et nos “MFE”, Liferay a prévu un CX de type “CustomElement” qui nous permet de déclarer notre “CustomElement” (ou RemoteApp) et de le transformer en widget que l’on va pouvoir déposer à l'endroit souhaité sur nos pages.
On pourra aussi le configurer pour faire en sorte qu’un même MFE puisse se comporter différemment en fonction de sa configuration.
Il est aussi possible d’avoir une ou plusieurs instances d'un même MFE par page mais cela implique de faire très attention à la façon de coder pour ne pas avoir d’interférences.

Pour déclarer un MFE, il faut simplement ajouter un CX de type “Custom Element” et le configurer de cette façon :

Ici, on retrouve ce qui avait été déclaré dans le fichier “index.html” de notre projet Angular (voir mon premier article).
On indique les ressources JS (ici il y en a 2) et les ressources CSS (ici une seule), puis on va aussi indiquer si on activera le mode modulaire (ES Build : ce qui va nous permettre d’utiliser les importMaps) et si on veut que notre MFE soit instanciable ou non. Pour rappel, si un élément est instanciable, on pourra le déposer plusieurs fois sur une même page, sinon on ne poura le déposer qu'une seule fois par page.
Dans les 2 cas, on pourra, au moyen de la configuration, faire en sorte que leur comportement ou leur affichage soit différent.

4 - Intégrer des “ImportMaps”

Ensuite, il nous reste à déclarer nos importMaps, car ce sont aussi des CX, qui pourront être ajoutés sur une page, plusieurs pages (au niveau de la Master Page) ou toutes mes pages (au niveau du Thème).
Sachant que Liferay intègre déjà nativement tous les importMaps pour React 18 (mais pas pour Angular). Il est donc beaucoup plus simple de faire du React en Liferay.
Pour déclarer un ImportMap, on procédera de la même façon que précédemment :

Ici, j’ai déclaré un importMap que j’ai appelé avec le même “spécificateur” que celui utilisé dans ma RemoteApp Angular 19, et l’url utilisée sera la même que celle déclarée dans le “head” du fichier “index.html”.
Je peux aussi décider de télécharger ce fichier et l’héberger sur mon Liferay (Liferay intègre une GED qui historise nativement les fichiers) ou sur mon Nginx.

5 - Intégrer d'autres ressources

Il sera aussi possible d'intégrer d'autres ressources sous la forme de CX (Client eXtension). Comme par exemple des fichiers statiques JS ou CSS mais aussi des surcharges de fichiers du thème par défaut de Liferay (en mode SaaS, on ne peut pas ajouter de thème mais on pourra surcharger le thème par défaut pour modifier uniquement notre instance).

Il sera aussi possible d'ajouter des CX de type micro-service ou batch, voir la page Liferay pour en connaître la liste exhaustive : https://learn.liferay.com/w/dxp/liferay-development/client-extensions

6 - Intégrer des styles

Il est aussi possible de créer des styles, Liferay permet de créer des feuilles de styles qui pourront être appliquées par page ou par site.

De cette façon, je vais pouvoir créer un design system commun pour plusieurs pages, un site entier ou plusieurs sites.

Il sera possible de “brander” un site aux couleurs de Canon, Apple, Philips ou autre…

Un même site pourra hériter de styles CSS entre toutes ses pages et je ne parle pas que de couleurs, mais aussi de bordures, d’arrondis, de fontes, d'espacements, de titres…

Ci-dessus, la version “Canon” de mon site et ci-dessous, la version “Philips” :

Et voici la configuration l’éditeur des feuilles de styles si je voulais créer un site “Apple” :

Sur la partie gauche je peux visualiser la page de mon choix et sur la partie droite je peux modifier en temps réel les couleurs, bordures, espacements, titres… jusqu’à obtenir l’effet souhaité.

7 - Intégrer des sites

Liferay propose aussi de créer des templates de pages ou de sites.

Il est possible de créer une ou plusieurs usines à sites qui auront des pages communes avec des styles différents, une favicon différente, un logo différent et bien sûr des données différentes.

Chaque site peut avoir des paramétrages différents et chaque MFE pourra s'afficher différemment puisqu'il va hériter du CSS du site en cours mais aussi de son paramétrage.
On peut par exemple dans notre MFE récupérer les données avec un identifiant technique configuré sur chacun des sites.

8 - Intégrer des MFEs entre eux

Étant donné que les MFEs peuvent être sur une même page, ils profitent des mêmes styles CSS mais aussi des mêmes objets javascripts.

Liferay expose différentes méthodes javascripts comme Liferay.fire(), Liferay.on(), Liferay.Util, Liferay.ThemeDisplay, Liferay.Session, Liferay.Service…

Un MFE présent sur une page Liferay peut donc accéder à toutes ces méthodes et objets JS et interagir avec les autres composants sur cette même page. Il peut donc récupérer le contexte de la page en cours (quel utilisateur est connecté, est-il en mode substitution, dans quelle langue, sur quelle page…) mais aussi déclencher un rafraîchissement d'un autre composant, lui envoyer des données, l'écouter, naviguer vers une autre page… et cet autre composant pourra être un MFE, un widget Liferay ou un fragment Liferay.

Il est donc très facile d'interagir avec le panier ou l'avatar pour lui envoyer une information ou lui demander de se rafraîchir et ainsi qu'il mette à jour son compteur de notification ou d'articles dans le panier.

Enfin si on veut faire persister des donnés, on peut appeler un webservice Liferay, sans besoin de fournir nos informations de connexion.

Dans l'animation ci-dessus, pour la communication entre mes 2 MFEs n’ayant pas conscience l’un de l’autre, j’ai utilisé le “Liferay.fire()” présent nativement dans toutes les pages Liferay pour envoyer un objet JS :

Et du côté de la “RemoteApp” Angular 19, j’ai utilisé le “Liferay.on()” :

Ensuite, il est possible d’interagir avec tous les éléments présent à l’écran et c’est ce que j’ai fait dans l'animation ci-dessous entre un MFE Angular et le fragment avatar natif de Liferay :

Dans cette animation, on voit que lorsque j’effectue une modification sur le profil de l’utilisateur, le webservice que j’ai créé et appelé par mon MFE va ajouter une notification à destination de ce même utilisateur. Le MFE va donc demander un rafraichissement de l’avatar qui va actualiser sa pastille de notification. En cliquant dessus, je vais pouvoir accéder à toutes mes notifications pour modifier leur statut.

9 - Intégrer le cycle de vie des utilisateurs

Liferay s'occupe nativement de la gestion des utilisateurs, de la politique des mots de passe, de leurs rôles, permissions et de leur session.

Liferay peut aussi déléguer à un IdP (Identity Provider) en OIDC, SAML, CAS… et peut gérer la réplication de sessions.
En cas de coupure de réseau, ou de problème sur un serveur, Liferay peut fonctionner en mode cluster et répliquer les sessions des utilisateurs afin qu'il n'y ait aucune perte de session.
Et même si ce cas est rare, il peut s'avérer utile lors des déploiements de nouvelles versions… on pourra donc assurer un service 24h/24 et 7j/7 sans interruption de service.

10 - Intégrer les publications

Liferay propose aussi nativement le principe de Publications, on va donc pouvoir expérimenter en avance de phase une nouvelle version de nos pages ou configurations sans affecter la production et programmer notre publication à une date définie à l'avance et même pouvoir faire un retour en arrière en cas de problème.

Il est aussi possible de définir des MFEs présents sur un autre domaine et donc de pouvoir tester nos MFEs localhost sans besoin de les déployer réellement.
Un cas d'usage extrêmement pratique est de déclarer nos MFEs locaux sur un environnement de test. Ainsi nos développeurs frontends n'aurons pas besoin d'installer un Liferay sur leur poste, ils pourront exécuter leur application javascript localement et l'intégrer facilement sur le site d'intégration ou de recette.
Un développeur frontend pourra tester son code dans un environnement donné sans impacter cet environnement puisqu'il sera sur un site dédié ou une page cachée d'un site donné.

11 - Intégrer le rafraîchissement des MFEs

Liferay permet de gérer le rafraîchissement des MFEs.
Nativement, lorsque qu'un MFE est inséré dans une page, un timestamp est ajouté automatiquement en paramètre et le navigateur va recharger les ressources du MFE affiché.

A chaque déploiement ou modification du “Custom Element”, le timestamp changera et provoquera son rechargement automatique sur toutes les pages le contenant.

Si le MFE est hébergé sur le Liferay, à chaque déploiement il sera modifié et donc sera rechargé. Mais si il est hébergé ailleurs (cas d'une remoteApp), il y a deux solutions simples :

  • soit modifier manuellement le CX déclaré dans Liferay et donc provoquer son rechargement.

  • soit prévoir un mécanisme de mise à jour automatique toutes les X minutes en utilisant par exemple le mécanisme natif de “scheduler” de Liferay qui ira interroger la version déployée de la “RemoteApp”.

12 - Conclusion

Avec ce second article j'ai parcouru beaucoup de fonctionnalités de Liferay. Toutes sont disponibles dans la version CE mais la version DXP apporte un support et 4 versions annuelles dont une maintenue 5 années. La version CE elle ne propose qu'une seule version par an même si il est possible à tout moment de surcharger une partie ou de générer une version en partant du code source disponible sur GitHub.

Cet outil est très facile à prendre en main, même si il propose énormément d'options.

Les images dockers sont disponibles ici pour la version CE et ici pour la version DXP.
Par défaut, les images docker fonctionnent dans un mode “démo”, c'est à dire avec une base de données fichiers et un ElasticSearch “SideCar”. Il est important de modifier la configuration par défaut dans un projet réel.
La version DXP est inclue avec une licence de 30 jours permettant de tester facilement cette version.

Si vous voulez mettre en place une micro-architecture comme évoquée dans cet article, n'hésitez pas à me solliciter ou à solliciter Niji pour une démonstration, des conseils, une prestation d'installation, une formation ou encore un projet clé en main !

En fonction de la volumétrie et surtout du nombre de connexions simultanées, il sera possible de faire une installation très simple avec un PostgreSQL et un Tomcat (serveur exposant le Liferay) sur une simple VM ou partir sur une architecture Kubernetes avec plusieurs réplicats (en mode cluster) et un ElasticSearch.

Si vous m'avez lu jusqu'ici, merci de m'ajouter un like 👍 ou de me laisser un commentaire ✍️ !

0
Subscribe to my newsletter

Read articles from Eric DARIEL directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Eric DARIEL
Eric DARIEL