10. Oct 2022Frontend

Micro Frontends - Používanie prístupu microservices pri frontend vývoji

V dnešnom online svete prichádzame do styku s rôznymi webovými appkami. Od drobných nástrojov a projektov až po portály a cloudové aplikácie, ktoré zahŕňajú celú sadu rôznych funkcionalít a možností. Pri vývoji veľkých a komplexných webových appiek, čelia vývojárske tímy zpravidla rovnakým výzvam. Ako možnosť, ktorá by riešila tieto problémy, sa začala javiť micro frontends architektúra.

Ján CvenčekFrontend Develooper

O architektúre sa začalo hlbšie diskutovať a analyzovať zhruba v roku 2015. V roku 2016 bola jej idea predstavená v Technology radar.

Idea vychádza z architektúry Microservices, ktorá popisuje spôsob, akým monolitický backend rozdeliť na viacero menších logických celkov, ktoré spoločne navzájom spolupracujú. Jednou z prvých väčších firiem, ktoré sa rozhodli architektúru micro frontends (MFE) použiť, bola Ikea. Neskôr sa tento koncept osvedčil a použili ho ďalšie firmy ako DAZN, Spotify, Soundcloud, Zalando ai.

Akým výzvam môžu tímy pri veľkých projektoch čeliť? Napr.:

  • narastajúcu komplexnosť aplikácie,
  • organizačné problémy,
  • pomalý onboarding pre nových členov tímu,
  • škálovateľnosť,
  • rýchlosť dodania inovácii do aplikácie,
  • nezávislý deployment.

Koncept architektúry

Príkladom pre aplikáciu, ktorá zahŕňa viacero funkčných častí môže byť web banky. Obsahuje napr. klientsku zónu, internet banking, sekciu pre médiá, sekciu pre investorov, atď. Každá spomenutá časť predstavuje logický celok, ktorý by vedel existovať ako samostatná aplikácia.  Ideou MFE je rozdeliť veľkú komplexnú webovú aplikáciu (napr. Single Page Application) na menšie logické celky, ktoré navzájom komunikujú a spolupracujú. Takéto celky predstavujú samostatné sub-aplikácie (SubApp). Cieľom je dosiahnuť nízku mieru vzájomnej závislosti medzi SubApps a snažiť sa o čo najväčšiu izolovanosť a logickú celistvosť.

Koncept architektúry Single Page vs Micro frontends

Výhody MFE

Možnosť použitia rôznych technológii pre každú SubApp:

  • voľnosť pri implementácii s využitím frameworku napr. React, Angular, Vue, …
  • vlastný koncept pre štýlovanie: Sass, Scss, StyledComponents, Tailwind, Bootstrap, …
  • výber v akom jazyku bude kód písaný napr. Javascript alebo Typescript

Autonómne tímy - každá SubApp môže byť vyvíjaná iným tímom vývojárov, ktorí si nastavia vlastné procesy, konvenciu, postupy atď. nezávisle od ostatných tímov. Ich fungovanie nie je priamo ovplyvnené iným tímom. Zahŕňa to nezávislosť pri vývoji, nasadzovaní a manažmente.

Izolácia chybových stavov - ak zlyhá jedna SubApp neovplyvní to ostatné a samotná aplikácia ako celok bude fungovať ďalej.

Rýchlejší onboarding - nový člen tímu bude pracovať na vývoji SubApp, ktorej komplexnosť je omnoho menšia v porovnaní s celou aplikáciou, ak by bola stavaná ako monolit. Nemusí tým pádom poznať všetky užívateľské scenáre, väzby medzi logickými blokmi a celkovú myšlienku.

HR možnosti pri nábore - nadväzuje priamo na prvú spomenutú výhodu. Ak aplikácia nie je striktne postavená iba na jedinom frameworku, pri hľadaní nových ľudí na projekt nie je nutné sa striktne zameriavať iba na jedinú technológiu. Na projekte tak nájdu uplatnenie ľudia s rôznymi technologickými znalosťami: React vývojár, Angular vývojár, …

Vývoj inovácií a nových funkcionalít  do budúcna - vďaka slabej vzájomnej prepojenosti medzi jednotlivými SubApps je zmena/vylepšenie/rozšírenie aktuálnej implementácie menej náročná. Nakoľko to nemá dopad skrz celú aplikáciu, ale iba na konkrétnu SubApp.

Nevýhody MFE

UX/UI konzistentnosť - je potrebné dodržiavať jednotné dizajny a UX flowy skrz celú aplikáciu, aby sa javila ako jednoliata.

Duplicita kódu - väčší predpoklad, že sa budú opakovať časti kódu, ktoré riešia rovnakú problematiku skrz jednotlivé SubApps.

Technologické problémy - správne nastavenie celého projektu, vzájomné prepojenie SubApps, debugging a monitoring, použitie rovnakých názvosloví pre globálne premenné, override CSS štýlov,… To všetko sú výzvy, ktorým treba čeliť pri použití MFE architektúry. Pre jej úspešné použitie je nutná aj nemalá porcia vedomostí o jednotlivých technológiách a architektúre samotnej.

Testovanie - jednoduchšie z pohľadu SubApp ale náročnejšie z pohľadu aplikácie ako celku. Je potreba nielen otestovať jednotlivé SubApps ale aj jednotlivé integrácie medzi nimi.

Náročnejšia analýza - správne identifikovať logický rozsah a čo konkrétne má daná SubApp zastrešovať. Taktiež komunikačné rozhranie medzi jednotlivými SubApps, aby bolo univerzálne, jednoduché a nenútilo k silnej závislosti a previazanosti jednotlivých častí.

Typy integrácií

Kostru celej aplikácie postavenej na MFE architektúre zabezpečuje kontajner. Jedná sa o riadiaci prvok, ktorý rozhoduje, kedy a kde sa má daná SubApp zobraziť.

Integrácia - ako a kedy získa kontajner prístup k zdrojovým kódom jednotlivých SubApps

Existujú 3 typy integrácií, ako sa jednotlivé SubApps vzájomne prepájajú s kontajnerom a vytvoria funkčný celok.

Build-time (compile-time)

Predtým ako sa kontajner načíta v prehliadači, získa prístup k zdrojovému kódu požadovanej SubApp.

Jednotlivé SubApps sú integrované do Kontajnera ako moduly (závislosti). Build SubApp vytvorí modul, ktorý sa zahrnie do Kontajnera a je obsiahnutý v jeho výslednom builde. Zmena v SubApp spôsobí, že je vyžadovaný ďalší build a nasadenie Kontajnera s novou verziou SubApp.

Integráciu je jednoduché nastaviť a porozumieť jej. Nevýhodou je opätovný deploy Kontajnera, pri každej zmene (verzie) SubApp, ktorú chceme reflektovať vo finálnej aplikácii. Taktiež láka na pevné prepojenie Kontajner + SubApp(s).

Run-time (client-side)

Potom ako sa kontajner načíta v prehliadači, získa prístup k zdrojovému kódu požadovanej SubApp.

Jednotlivé SubApps bežia samostatne remote na definovanej ceste. Kontajner má definované, na akej ceste je aká SubApp dostupná. Zmena verzie SubApp nevyžaduje re-deploy Kontajnera a je reflektovaná okamžite. Rôzne verzie SubApp môžu mať definované odlišné cesty.

Integrácia je zložitejšia na setup, no nevyžaduje dodatočný deploy Kontajnera pri zmene SubApp. Taktiež deploy samotnej SubApp je nezávislý.

Server (Server side rendering)

Počas renderovania kontajnera, server rozhodne, či má alebo nemá byť zahrnutý zdrojový kód požadovanej SubApp.

Ukladá zdrojové kódy SubApps do CDN a skladá ich do výsledného zobrazenia, ktoré je neskôr servované počas build-time alebo run-time. Princípy sú ďalej podobné podľa toho, kedy je výsledné zobrazenie servované.

Frameworky pre MFE

Bit

Jeden z najpopulárnejších frameworkov pre MFE. Umožňuje vytvárať a manažovať SubApps skrz nezávislé komponenty. Ich homepage je príklad toho, ako samotný framework funguje. Používa build-time integráciu.

Bit framework concept

Module Federation

Umožňuje vyvíjať viacero separátnych buildov bez závislosti od kódu iných celkov. Každý je vyvíjaný a nasadzovaný nezávisle. Používa run-time integráciu. Webpack od verzie 5 ponúka možnosť použitia pluginu Module Federation.

Module Federation concept

Single SPA

Princíp spočíva v tom, že každá SubApp môže reagovať na eventy z URL routingu a musí byť podporovať akcie pre bootstrap, mount a unmount. Odlišnosť od tradičných SPA je v tom, že tu musia byť aplikácie postavené tak, aby mohli koexistovať s ostatnými. Nie je nevyhnutné, aby každá SubApp mala vlastnú HTML stránku. Aspoň jedna SubApp (Kontajner) musí byť remote hostovaná. Používa run-time integráciu.

Single SPA concept

Ďalšie frameworky

Záver

Ak počas vývoja projektu sa objavia problémy, ktoré by mohli byť motiváciou vydať sa cestou MFE architektúry, určite to treba zvážiť. Osvedčila sa v praxi a implementovali ju veľké firmy ako Ikea alebo Spotify. Treba mať na pamäti, že MFE architektúra prináša benefity, ale zahŕňa aj úskalia.  Je dôležité, aby sa architekt správne rozhodol, ktorá forma integrácie bude na projekte implementovaná. Treba dbať na dodržiavanie princípov definovaných pre túto architektúru a snažiť sa vedomostne pokryť celý koncept, aby sa projekt dostal do úspešného konca. Ako odrazový mostík, kde začať môže poslúžiť web micro-frontends.org

Ján CvenčekFrontend Develooper