{"id":6363,"date":"2023-06-12T12:45:07","date_gmt":"2023-06-12T10:45:07","guid":{"rendered":"https:\/\/www.luklagroup.com\/sem-categoria\/architecture-micro-frontends-communication-et-strategie-de-tests\/"},"modified":"2023-06-12T12:45:07","modified_gmt":"2023-06-12T10:45:07","slug":"architecture-micro-frontends-communication-et-strategie-de-tests","status":"publish","type":"post","link":"https:\/\/www.luklagroup.com\/pt-pt\/web-marketing-pt-pt\/architecture-micro-frontends-communication-et-strategie-de-tests\/","title":{"rendered":"Architecture micro frontends &#8211; Communication et strat\u00e9gie de tests"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Nous avons pr\u00e9sent\u00e9 dans un <a href=\"https:\/\/digiwin.fr\/actualites\/architecture-micro-frontends\/\">pr\u00e9c\u00e9dent article<\/a> l&#8217;architecture micro frontends. Si vous n&#8217;\u00eates pas familier de ce type d&#8217;architecture, je vous conseille vivement de commencer par la lecture de celui-ci. Dans cet article, nous allons aborder plusieurs points de conception li\u00e9s \u00e0 ce type d&#8217;architecture, notamment sur la communication entre micro frontends et sur la strat\u00e9gie de tests. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">La communication entre micro frontends<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Le but de l&#8217;architecture micro frontends est de d\u00e9coupler au maximum les diff\u00e9rentes parties d&#8217;une application. Mais voil\u00e0, le plus souvent certaines parties doivent interagir entre elles. Elles doivent pouvoir communiquer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Comment faire, alors que chaque micro frontends est potentiellement r\u00e9alis\u00e9 dans une technologie diff\u00e9rente&nbsp;?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pour ce faire, on peut utiliser simplement les param\u00e8tres d&#8217;url, avec toutes les limitations que \u00e7a implique. Mais il existe d&#8217;autres solutions, plus pratiques, que nous allons aborder ci-dessous.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Attributes + Properties<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Dans le cas particulier des Web Components, on peut passer des donn\u00e9es avec les attributs directement via le code HTML.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;product-details product-id=\"1234567890\"&gt;&lt;\/product-details&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">L&#8217;exemple utilise via une <code>properties<\/code> javascript l&#8217;identifiant du produit pour afficher les d\u00e9tails dudit produit.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const monWebComponent = document.getElementById(\"mon-web-component\")\n \nmonWebComponent.produit = {\n   id: \"1234567890\",\n   name: \"Mon produit\",\n   price: 30.5\n}\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Avantages<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">L&#8217;approche <code>attributes<\/code> est semblable au transfert de donn\u00e9es de composant parent \u00e0 composant enfant dans les frameworks SPA actuels. C&#8217;est donc une fa\u00e7on de faire intuitive pour les d\u00e9veloppeurs front.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dans le cas de l&#8217;approche <code>properties<\/code>, certaines librairies permettent m\u00eame de simplifier l&#8217;utilisation de ces derni\u00e8res en passant les donn\u00e9es &#8211; m\u00eame complexes &#8211; comme des <code>attributes<\/code>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Inconv\u00e9nients<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Le format de donn\u00e9es pass\u00e9 en <code>attributes<\/code> reste assez limit\u00e9, car n&#8217;acceptant que des donn\u00e9es sous forme de cha\u00eenes de caract\u00e8res.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ces donn\u00e9es sont directement visibles dans le code, \u00e0 bannir pour les donn\u00e9es sensibles !<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Dom \/ Custom Events<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Le DOM est notamment constitu\u00e9 d&#8217;une interface orchestrant les events, \u00e9v\u00e9nements qui ont lieu au sein de la page, qu&#8217;ils soient provoqu\u00e9s par l&#8217;utilisateur (clic de souris, touche enfonc\u00e9e par exemple), ou par d&#8217;autres \u00e9l\u00e9ments (vid\u00e9o\/audio en pause par exemple).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On peut cr\u00e9er et utiliser ces events pour faire passer des donn\u00e9es via l&#8217;\u00e9l\u00e9ment <code>window<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On distingue deux principes :<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>window.postMessage()<\/li><li>Custom Events.<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>\/* emitter.js *\/\nconst message = {\n type: \"important\",\n content: \"Ce message est important\",\n};\n\n\/\/ DOM Event\nwindow.postMessage(message, \"https:\/\/url-destinataire.fr\");\n\n\/\/ Custom Event\nconst event = new CustomEvent(\"message.important\", {\n detail: message\n});\nwindow.dispatchEvent(event);\n\n\/* receiver.js *\/\nwindow.addEventListener(\"message.important\", handleMessage);\n \nfunction handleMessage(event) {\n   \/\/ la donn\u00e9e est accessible dans event.data ou event.detail\n}\n\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Il est pr\u00e9f\u00e9rable de privil\u00e9gier les Custom Events \u00e0 <code>window.postMessage(<\/code>) dans tous les cas d&#8217;usage \u00e0 l&#8217;exception des <code>iframe<\/code> qui ne permettent que l&#8217;utilisation de cette derni\u00e8re m\u00e9thode (\u00e0 cause de leur encapsulation particuli\u00e8re).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La m\u00e9thode <code>window.postMessage()<\/code> peut \u00eatre appel\u00e9e depuis et vers n&#8217;importe quel domaine, il faut \u00eatre particuli\u00e8rement vigilant \u00e0 la r\u00e9ception dans un souci de s\u00e9curit\u00e9 applicative.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Avantages<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Leur utilisation est simple.<br>Elle permet d&#8217;assurer la r\u00e9activit\u00e9 des donn\u00e9es entre les micro frontends d&#8217;une m\u00eame page.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Inconv\u00e9nients<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Leur utilisation cr\u00e9e des couplages directs entre les applications \u00e9mettrices et r\u00e9ceptrices, couplages que l&#8217;on cherche justement \u00e0 \u00e9viter.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La gestion des diff\u00e9rents events peut devenir rapidement complexe en fonction de leur nombre.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">State Management<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">L&#8217;approche composant apport\u00e9e par les frameworks comme React ou Vue entra\u00eene des d\u00e9pendances parent-enfants pour le passage de donn\u00e9es.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pour \u00e9viter cette complexit\u00e9, les solutions de state management Redux (pour React), Vuex (pour Vue) et NGRX (pour Angular) permettent \u00e0 tout composant d&#8217;avoir le m\u00eame niveau d&#8217;acc\u00e8s et d&#8217;\u00e9criture aux donn\u00e9es partag\u00e9es de l&#8217;application, rendues ind\u00e9pendantes des composants.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On peut appliquer ce concept sur plusieurs micro frontends : une solution est d&#8217;attacher nos m\u00e9thodes de lecture (selectors\/getters) et de modification (actions) au window.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Avantages <\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">La donn\u00e9e partag\u00e9e est disponible \u00e0 tout endroit de l&#8217;application, et ind\u00e9pendante de tout micro frontends.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Elle persiste ind\u00e9pendamment des cycles de vie des micro frontends.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Utiliser Vuex, Redux ou Ngrx permet de conserver la mise \u00e0 jour des donn\u00e9es de fa\u00e7on r\u00e9active.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Inconv\u00e9nients<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Cette solution (via window) reste n\u00e9anmoins <strong>dangereuse <\/strong>: n&#8217;importe qui peut avoir acc\u00e8s \u00e0 cet \u00e9l\u00e9ment via la <strong>console du navigateur<\/strong> et donc avoir acc\u00e8s \u00e0 toutes les donn\u00e9es communes en lecture <strong>et en \u00e9criture<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Session Storage \/ Local Storage \/ Cookies<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">La communication de donn\u00e9es au sein d&#8217;une architecture micro frontends peut aussi passer par les solutions de stockages de donn\u00e9es du navigateurs. Il en existe plusieurs, voici les 3 principaux :<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>sessionStorage<\/code> : la donn\u00e9e stock\u00e9e est accessible uniquement <strong>dans un onglet<\/strong>. Elle ne survie pas \u00e0 la fermeture de celui-ci. <\/li><li><code>localStorage<\/code> : la donn\u00e9e stock\u00e9e est partag\u00e9e par <strong>tous les onglets<\/strong> du navigateur provenant de la m\u00eame origine. Elle survie au red\u00e9marrage de celui-ci, et m\u00eame du syst\u00e8me.<\/li><li><code>cookies<\/code> : la donn\u00e9e stock\u00e9e est accessible par <strong>tous les onglets<\/strong> du navigateur provenant de la m\u00eame origine. La dur\u00e9e de vie est ajustable selon les besoins.<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Avantages <\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Tout comme le state management, l&#8217;avantage principal de ces m\u00e9thodes est de pouvoir avoir acc\u00e8s en lecture et en \u00e9criture \u00e0 des donn\u00e9es globales en tout point de l&#8217;application et d&#8217;\u00eatre totalement ind\u00e9pendant des changements de pages.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Inconv\u00e9nients<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">On retrouve les m\u00eames inconv\u00e9nients que pr\u00e9c\u00e9demment : ces donn\u00e9es sont <strong>accessibles et modifiables par l&#8217;utilisateur<\/strong> directement dans la console, attention donc \u00e0 la s\u00e9curit\u00e9 applicative.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Les objets stock\u00e9s ne sont qu&#8217;au format <strong>cha\u00eene de caract\u00e8res<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ces donn\u00e9es sont &#8220;rigides&#8221; : une modification n&#8217;entra\u00eenera pas de mise \u00e0 jour dynamique dans les applications, mais seulement au rafra\u00eechissement ou au changement de page.<br>Le volume de donn\u00e9es du <code>localStorage<\/code> est limit\u00e9 par application, selon les navigateurs. De m\u00eame pour les cookies o\u00f9 la limite est m\u00eame bien plus basse.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Communiquer avec une API<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Si nous avons des \u00e9quipes distinctes travaillant ind\u00e9pendamment sur chaque micro frontend, quid du d\u00e9veloppement backend ?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">L&#8217;avantage des \u00e9quipes &#8220;full-stack&#8221; est qu&#8217;elles sont propri\u00e9taires du d\u00e9veloppement de leur application, du code visuel jusqu&#8217;au d\u00e9veloppement de l&#8217;API, etc.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Le mod\u00e8le \u00e0 appliquer est le pattern <a href=\"https:\/\/samnewman.io\/patterns\/architectural\/bff\/\" rel=\"nofollow\">BFF<\/a> : Backend For Frontend.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Chaque application frontale a un backend d\u00e9di\u00e9 dont le but est de r\u00e9pondre uniquement aux besoins de ce frontend<\/strong> (\u00e0 l&#8217;origine ce mod\u00e8le \u00e9tait destin\u00e9 \u00e0 avoir un backend pour mobile, un pour desktop, etc.).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Le BFF peut \u00eatre autonome avec sa propre logique m\u00e9tier, sa propre base de donn\u00e9es, ou \u00eatre un agr\u00e9gateur de services.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">L&#8217;id\u00e9e est ici que <strong>l&#8217;\u00e9quipe qui construit un micro frontend ne devrait pas avoir \u00e0 attendre que d&#8217;autres \u00e9quipes construisent des choses pour elle<\/strong> (attendre qu&#8217;un web service soit d\u00e9velopp\u00e9 par l&#8217;\u00e9quipe backend et utiliser, en attendant, des donn\u00e9es mock\u00e9es qui finalement, risquent de ne pas correspondre exactement aux donn\u00e9es \u00e9mises par le service).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Donc, si chaque nouvelle fonctionnalit\u00e9 ajout\u00e9e \u00e0 une micro-interface n\u00e9cessite \u00e9galement des modifications du back-end, c&#8217;est un cas solide pour un BFF, appartenant \u00e0 la m\u00eame \u00e9quipe.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A contrario, si le micro frontend n&#8217;a qu&#8217;une seule API avec laquelle il \u00e9change et que cette API est assez stable, il n&#8217;y a peut-\u00eatre pas beaucoup d&#8217;int\u00e9r\u00eat \u00e0 cr\u00e9er un BFF.<\/p>\n\n\n\n<figure class=\"wp-block-image size-medium is-style-default\"><img decoding=\"async\" src=\"https:\/\/digiwin.fr\/wp-content\/uploads\/2023\/06\/image-900x410.png\" alt=\"Illustration du pattern Backend For Frontend au sein d'une architecture micro frontends\" class=\"wp-image-4625\"\/><figcaption>Le pattern Backend For Frontend<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Comment l&#8217;utilisateur d&#8217;une application micro frontends doit-il \u00eatre authentifi\u00e9 et autoris\u00e9 aupr\u00e8s du serveur ?<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Les utilisateurs ne devraient avoir \u00e0 s&#8217;authentifier qu&#8217;une seule fois. Par cons\u00e9quent, l&#8217;authentification doit appartenir \u00e0 l&#8217;application conteneur.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">L&#8217;app conteneur a probablement une sorte de formulaire de connexion, \u00e0 travers lequel nous obtenons un jeton d&#8217;acc\u00e8s. Ce jeton devrait alors appartenir au conteneur et pourrait \u00eatre inject\u00e9 dans chaque micro frontend lors de son initialisation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Enfin, le micro frontend peut envoyer le jeton avec n&#8217;importe quelle demande qu&#8217;il adresse au serveur, et le serveur peut effectuer les validations requises.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Strat\u00e9gie de tests<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Le mod\u00e8le d&#8217;architecture micro frontends cr\u00e9e de la complexit\u00e9 technique.<br>Or qui dit complexit\u00e9 technique, dit n\u00e9cessit\u00e9 de mettre en place un solide harnais de tests automatis\u00e9s, sans quoi notre superbe architecture risque d&#8217;\u00eatre un fiasco.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pour rappel les tests automatis\u00e9s se d\u00e9composent principalement en tests unitaires, d&#8217;int\u00e9gration, et end to end (cf. l&#8217;article OCTO : <a href=\"https:\/\/blog.octo.com\/la-pyramide-des-tests-par-la-pratique-1-5\/\">La pyramide des tests par la pratique<\/a>).<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Les tests unitaires v\u00e9rifient le comportement d&#8217;une portion de code totalement ou partiellement isol\u00e9e de ses d\u00e9pendances.<\/li><li>Les tests d&#8217;int\u00e9gration v\u00e9rifient que plusieurs composants fonctionnent ensemble.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Chaque micro frontend \u00e9tant une application ind\u00e9pendante, il doit avoir ses propres tests unitaires et d&#8217;int\u00e9gration<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En plus de ces tests, on pourra ajouter des <a href=\"https:\/\/blog.octo.com\/la-pyramide-des-tests-par-la-pratique-4-5\/\">tests de contrats<\/a>, tests \u00e0 mi-chemin entre unitaires et d&#8217;int\u00e9gration, ind\u00e9pendants des micro frontends, et qui vont s&#8217;assurer que la communication inter-applications est op\u00e9rationnelle en v\u00e9rifiant que les interfaces sont bien respect\u00e9es \u00e0 l&#8217;\u00e9mission et la r\u00e9ception des donn\u00e9es.<br>Ainsi, s&#8217;il y a un breaking change, on sait quel micro frontend est responsable. Enfin les tests end-to-end servent \u00e0 v\u00e9rifier le bon fonctionnement d&#8217;un parcours utilisateur du d\u00e9but \u00e0 la fin de sa navigation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ce sont ces tests qui vont nous assurer que la cohabitation des micro frontends est coh\u00e9rente et que l&#8217;application est utilisable.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ces tests sont plus longs \u00e0 ex\u00e9cuter, moins il y aura d&#8217;interactions entre les micro frontends, plus ces tests seront succincts, et donc rapides \u00e0 ex\u00e9cuter.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Or une modification sur un micro frontend entra\u00eene une modification sur l&#8217;application globale : la CI de notre application doit ex\u00e9cuter les tests end-to-end \u00e0 chaque fois, et on a encore une fois tout int\u00e9r\u00eat \u00e0 rendre les micro frontends les plus ind\u00e9pendants possible.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">N.B. : le framework de tests end-to-end <a href=\"https:\/\/www.cypress.io\/\">Cypress<\/a> a l&#8217;avantage de pouvoir passer outre l&#8217;encapsulation du Shadow.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nous avons pr\u00e9sent\u00e9 dans un pr\u00e9c\u00e9dent article l&#8217;architecture micro frontends. Si vous n&#8217;\u00eates pas familier de ce type d&#8217;architecture, je vous conseille vivement de commencer par la lecture de celui-ci. Dans cet article, nous allons aborder plusieurs points de conception li\u00e9s \u00e0 ce type d&#8217;architecture, notamment sur la communication entre micro frontends et sur la [&hellip;]<\/p>\n","protected":false},"author":9,"featured_media":6364,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_seopress_robots_primary_cat":"","_seopress_titles_title":"","_seopress_titles_desc":"","_seopress_robots_index":"","footnotes":""},"categories":[183,184,182],"tags":[],"class_list":["post-6363","post","type-post","status-publish","format-standard","has-post-thumbnail","category-apps-data-pt-pt","category-change-adopt-pt-pt","category-web-marketing-pt-pt"],"_links":{"self":[{"href":"https:\/\/www.luklagroup.com\/pt-pt\/wp-json\/wp\/v2\/posts\/6363","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.luklagroup.com\/pt-pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.luklagroup.com\/pt-pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.luklagroup.com\/pt-pt\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/www.luklagroup.com\/pt-pt\/wp-json\/wp\/v2\/comments?post=6363"}],"version-history":[{"count":0,"href":"https:\/\/www.luklagroup.com\/pt-pt\/wp-json\/wp\/v2\/posts\/6363\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.luklagroup.com\/pt-pt\/wp-json\/wp\/v2\/media\/6364"}],"wp:attachment":[{"href":"https:\/\/www.luklagroup.com\/pt-pt\/wp-json\/wp\/v2\/media?parent=6363"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.luklagroup.com\/pt-pt\/wp-json\/wp\/v2\/categories?post=6363"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.luklagroup.com\/pt-pt\/wp-json\/wp\/v2\/tags?post=6363"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}