Ukratko

Najvažnije iz članka

  • Mikrofrontendi dijele monolitni frontend na manje, neovisno razvijane i implementirane dijelove, poboljšavajući skalabilnost, održivost i agilnost tima.
  • Ključni arhitektonski patterni uključuju integraciju na razini builda, poslužitelja, klijenta (iframes, JavaScript) i rubne mreže, a odabir ovisi o specifičnim potrebama projekta.
  • Izazovi poput dijeljenja stanja, komunikacije, konzistentnosti dizajna i performansi rješavaju se primjenom event busa, globalnog stanja, dijeljenog UI kita, CSS izolacije i lazy loadinga.
  • Alati poput Webpack Module Federation, Single-SPA i Web Components ključni su za efikasnu orkestraciju i implementaciju mikrofrontend arhitektura.
Sadržaj članka
  1. Uvod u Mikrofrontende: Razbijanje Monolita na Skalabilne Komponente
  2. Zašto Mikrofrontendi?
  3. Arhitektonski Patterni za Mikrofrontende
  4. 1. Mikrofrontendi na Razini Builda (Build-time Integration)
  5. 2. Mikrofrontendi na Razini Slanja (Server-side Composition)
  6. 3. Mikrofrontendi na Razini Klijenta (Client-side Composition)
  7. 4. Mikrofrontendi na Razini Edge-a (Edge-side Composition)
  8. Ključni Izazovi i Rješenja
  9. Dijeljenje Stanja i Komunikacija
  10. Konzistentan Dizajn i Korisničko Iskustvo
  11. Performanse
  12. Upravljanje Implementacijom i Infrastrukturom
  13. Alati i Tehnologije
  14. Primjer Implementacije (Client-side s Module Federation)
  15. Zaključak

Uvod u Mikrofrontende: Razbijanje Monolita na Skalabilne Komponente

U današnjem svijetu brzog razvoja softvera, tvrtke se neprestano suočavaju s izazovima skalabilnosti, održivosti i agilnosti. Tradicionalne monolitne frontend aplikacije, iako jednostavne za početni razvoj, često postaju "big ball of mud" kako rastu u funkcionalnosti i veličini tima. Održavanje, implementacija novih značajki i neovisno skaliranje postaju noćna mora. Upravo ovdje na scenu stupaju mikrofrontendi, arhitektonski pristup koji koncept mikroservisa primjenjuje na frontend, dijeleći ga na manje, neovisno razvijane, testirane i implementirane dijelove.

Ideja je jasna: umjesto jednog gigantskog frontenda, imamo kolekciju manjih, autonomnih web aplikacija koje se spajaju u jedinstveno korisničko iskustvo. Svaki mikrofrontend može biti razvijen od strane drugog tima, koristeći različite tehnologije (iako se to često izbjegava zbog konzistentnosti), i ima vlastitu bazu koda, CI/CD pipeline, pa čak i verzije. Krajnji rezultat je aplikacija koja je lakša za održavanje, fleksibilnija i omogućava timovima da rade neovisnije, ubrzavajući vrijeme izlaska na tržište.

Zašto Mikrofrontendi?

Prednosti mikrofrontenda su višestruke:

  • Nezavisno implementiranje (Deploy): Svaki mikrofrontend može se samostalno implementirati, smanjujući rizik i omogućavajući brže isporuke.
  • Tehnološka agnostičnost: Timovi mogu birati najbolje alate za svoj specifični zadatak, potencijalno smanjujući tehnički dug (iako se preporučuje određena razina standardizacije).
  • Skalabilnost timova: Manji, samostalni timovi mogu raditi na specifičnim dijelovima aplikacije bez prevelike koordinacije.
  • Održivost koda: Manje baze koda su lakše za razumijevanje, testiranje i održavanje.
  • Izolacija grešaka: Greška u jednom mikrofrontendu manje je vjerojatno da će srušiti cijelu aplikaciju.
  • Lakše nadogradnje: Prebacivanje na novu verziju okvira ili biblioteke može se raditi postupno, komponentu po komponentu.

Međutim, mikrofrontendi donose i vlastite izazove, kao što su složenost orkestracije, dijeljenje stanja, performanse i, ključno, održavanje konzistentnog korisničkog iskustva.

Arhitektonski Patterni za Mikrofrontende

Implementacija mikrofrontenda nije trivijalna i zahtijeva pažljivo planiranje. Postoji nekoliko ključnih arhitektonskih patterna koji pomažu u orkestraciji i integraciji ovih autonomnih jedinica.

1. Mikrofrontendi na Razini Builda (Build-time Integration)

Ovo je najjednostavniji pristup i često se koristi za početak. Različiti mikrofrontendi su zapravo zasebne biblioteke ili komponente koje se u fazi builda spajaju u jednu monolitnu aplikaciju. Alati poput Webpack Module Federation ili Lerna (za monorepo upravljanje) mogu biti korisni ovdje.

  • Prednosti: Jednostavnost implementacije, dobre performanse (jer je sve bundle-ano zajedno), minimizira složenost run-time integracije.
  • Nedostaci: Gubi se većina prednosti neovisnog implementiranja. Promjena u jednom mikrofrontendu zahtijeva rekompilaciju i re-implementaciju cijele aplikacije. Nije idealno za velike, distribuirane timove.

2. Mikrofrontendi na Razini Slanja (Server-side Composition)

Kod ovog pristupa, web poslužitelj (poput Node.js, Nginx, ili Edge Side Includes - ESI) je odgovoran za sastavljanje različitih dijelova stranice prije nego što se ona pošalje klijentu. Svaki mikrofrontend se izlaže kao zasebni HTTP endpoint, a poslužitelj ih kombinira.

  • Prednosti: Neovisno implementiranje, bolja kontrola nad SEO-om (server-side rendering), jednostavno dijeljenje resursa (npr. head tagova).
  • Nedostaci: Dodaje složenost poslužiteljskom dijelu. Potencijalne performanse mogu trpjeti zbog više mrežnih poziva na poslužitelju. Manje pogodno za dinamičke, single-page aplikacije.

3. Mikrofrontendi na Razini Klijenta (Client-side Composition)

Ovo je vjerojatno najčešći i najfleksibilniji pristup za moderni web. Glavna aplikacija (tzv. Container ili Shell) je odgovorna za učitavanje, prikazivanje i orkestraciju različitih mikrofrontenda u pregledniku. Postoji nekoliko varijanti:

a) Iframes

Najjednostavniji način za izolaciju. Svaki mikrofrontend živi unutar svog <iframe> elementa.

  • Prednosti: Potpuna izolacija (CSS, JS, globalni objekti), sigurno, relativno jednostavno za implementaciju.
  • Nedostaci: Loša korisnička iskustva (scrollanje, povijest preglednika, responzivnost), otežana komunikacija između iframova, dijeljenje sesije i konteksta je izazovno. Često se smatra anti-patternom osim za specifične slučajeve (npr. integracija legacy sustava).

b) JavaScript Integracija

Ovo je dominantan pristup. Glavna aplikacija dinamički učitava i montira JavaScript bundle-ove (mikrofrontende) u DOM. To se može postići na nekoliko načina:

  • Custom Elements (Web Components): Mikrofrontendi se eksponiraju kao standardni HTML custom elementi. Glavna aplikacija ih samo renderira. Pruža dobru izolaciju i interoperabilnost s različitim frameworkima.

  • JavaScript Framework Agnostic Approach: Koristi se sustav za učitavanje JavaScript modula (npr. SystemJS, Webpack Module Federation) koji dinamički povlači i izvršava kod mikrofrontenda. Ovo omogućuje da različiti mikrofrontendi budu napisani u različitim frameworkima (React, Angular, Vue).

  • Shared Library/Context: Kapsuliranje zajedničke funkcionalnosti (autentikacija, navigacija, UI kit) u zajedničke biblioteke koje koriste svi mikrofrontendi. To smanjuje duplikaciju i osigurava konzistentnost.

  • Prednosti: Najveća fleksibilnost, neovisno implementiranje, dobra kontrola nad korisničkim iskustvom, komunikacija među mikrofrontendima je moguća (putem globalnih event busova, custom events ili centraliziranog stanja).

  • Nedostaci: Složeniji upravljanje stanjem i komunikacijom, potencijalni problemi s performansama (veliki bundle-ovi), izazovi s konzistentnim stilom i UI/UX-om.

4. Mikrofrontendi na Razini Edge-a (Edge-side Composition)

Ovaj pristup je sličan server-side compositionu, ali se integracija događa bliže korisniku, na CDN-u ili u rubnoj mreži. Usluge poput Cloudflare Workers, AWS Lambda@Edge ili Akamai EdgeWorkers omogućuju izvršavanje koda na rubu mreže, što može kombinirati HTML fragmente ili čak izvršavati JavaScript za dinamičko sastavljanje stranica.

  • Prednosti: Izuzetne performanse (niska latencija), neovisno implementiranje, visoka skalabilnost.
  • Nedostaci: Ograničeni alati i ekosustav, složenost razvoja i debuggiranja na rubnoj mreži, potencijalni troškovi.

Ključni Izazovi i Rješenja

Dijeljenje Stanja i Komunikacija

  • Event Bus: Lagan i fleksibilan način za mikrofrontende da komuniciraju emitiranjem i slušanjem događaja. Može biti implementiran pomoću globalnog window objekta, biblioteka poput EventEmitter ili PubSubJS.
  • Globalno Stanje (Shared State): Za složenije slučajeve, centralizirano skladište stanja (npr. Redux, Zustand) može se dijeliti. Međutim, to može smanjiti neovisnost mikrofrontenda.
  • URL Parametri/Local Storage: Za jednostavnu, neizravnu komunikaciju.
  • Custom Events: Nativni preglednički mehanizam za komunikaciju između različitih DOM elemenata (ako koristite Web Components).

Konzistentan Dizajn i Korisničko Iskustvo

  • Shared UI Kit/Design System: Obavezno je imati centralizirani sustav dizajna (komponente, stilovi, tokeni) koji koriste svi mikrofrontendi. To osigurava jedinstven izgled i osjećaj. Alati poput Storybooka su neprocjenjivi.
  • CSS Strategije: Globalni CSS je opasan. Koristite CSS Modules, Styled Components, Emotion ili Shadow DOM (s Web Components) za izolaciju stilova.
  • Zajednička Navigacija i Autentikacija: Ove se funkcionalnosti obično nalaze u glavnom kontejneru ili se implementiraju kao poseban mikrofrontend koji je dostupan svim ostalima.

Performanse

  • Lazzy Loading: Učitavajte mikrofrontende samo kada su potrebni.
  • Code Splitting: Razdvojite bundle-ove na manje dijelove.
  • Caching: Agresivno keširanje statičkih asseta.
  • Minimizacija i Kompresija: Standardne optimizacije za web.
  • Uklanjanje Dupliciranog Koda: Koristite alate poput Webpack Module Federation za dijeljenje zajedničkih biblioteka (React, Vue, itd.) između mikrofrontenda. Ovo je ključno za smanjenje veličine bundle-ova.

Upravljanje Implementacijom i Infrastrukturom

  • CI/CD Pipeline: Svaki mikrofrontend bi trebao imati vlastiti, neovisan CI/CD pipeline.
  • Hosting: Mikrofrontendi se mogu hostati odvojeno, na različitim lokacijama ili CDN-ovima.
  • Verzioniranje: Važno je upravljati verzioniranjem mikrofrontenda kako bi se osigurala kompatibilnost. Semantičko verzioniranje je standard.

Alati i Tehnologije

  • Webpack Module Federation: Nativna podrška unutar Webpacka za dijeljenje koda između različitih bundle-ova. Izvrstan za microfrontend arhitekture, omogućujući runtime dijeljenje modula.
  • Single-SPA: Popularan framework za izgradnju mikrofrontend arhitektura, pruža life-cycle metode za učitavanje, montiranje i demontiranje aplikacija napisanih u različitim frameworkima.
  • SystemJS: Dinamički učitava JavaScript module. Može se koristiti za orkestraciju mikrofrontenda.
  • Luigi: SAP-ov open-source framework koji pruža SPA router i integracijski sloj za mikrofrontende, podržava i React i Angular.
  • OpenComponents: Specifikacija i set alata za isporuku HTML komponenti (mikrofrontenda) na zahtjev.
  • Piral (aka. Pilets): Framework za izgradnju "micro frontends from scratch" s fokusom na plug-in arhitekturu i dijeljeni kontekst.
  • Web Components (Custom Elements): Nativna preglednička tehnologija za stvaranje ponovno upotrebljivih komponenti. Pruža izvrsnu izolaciju.
  • Nx dev tools (Monorepos): Iako nije specifično za mikrofrontende, Nx pomaže u upravljanju velikim monorepoima, što je čest pristup za mikrofrontend projekte koji dijele zajedničke biblioteke i build konfiguracije.

Primjer Implementacije (Client-side s Module Federation)

Zamislite e-commerce aplikaciju s tri mikrofrontenda:

  1. Shell App (Container): Osnovni layout, navigacija, autentikacija.
  2. Product List App: Prikazuje popis proizvoda.
  3. Product Detail App: Prikazuje detalje pojedinog proizvoda.
  4. Cart App: Košarica za kupovinu.

Koristeći Webpack Module Federation, svaki od ovih mikrofrontenda bi bio zaseban Webpack projekt. Shell App bi djelovao kao Host aplikacija, a ostali kao Remote aplikacije.

Shell App (webpack.config.js):

// ...
new ModuleFederationPlugin({
  name: 'shell',
  remotes: {
    productList: 'productList@http://localhost:3001/remoteEntry.js',
    productDetail: 'productDetail@http://localhost:3002/remoteEntry.js',
    cart: 'cart@http://localhost:3003/remoteEntry.js',
  },
  shared: {
    react: { singleton: true, requiredVersion: '^18.0.0' },
    'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
  },
})
// ...

Product List App (webpack.config.js):

// ...
new ModuleFederationPlugin({
  name: 'productList',
  filename: 'remoteEntry.js',
  exposes: {
    './ProductList': './src/ProductList.jsx',
  },
  shared: {
    react: { singleton: true, requiredVersion: '^18.0.0' },
    'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
  },
})
// ...

Unutar Shell App koda, mogli biste dinamički uvoziti i renderirati komponente:

import React, { lazy, Suspense } from 'react';
import ReactDOM from 'react-dom/client';

const ProductList = lazy(() => import('productList/ProductList'));
const ProductDetail = lazy(() => import('productDetail/ProductDetail'));
// ...

function App() {
  // Route logic for showing different microfrontends
  const currentMicrofrontend = window.location.pathname.includes('/products/') ? 'detail' : 'list';

  return (
    <div>
      <h1>My E-commerce Shell</h1>
      <nav>
        {/* Navigation links */}
      </nav>
      <Suspense fallback={<div>Loading Microfrontend...</div>}>
        {currentMicrofrontend === 'list' && <ProductList />}
        {currentMicrofrontend === 'detail' && <ProductDetail productId="..." />}
        {/* ... and so on for Cart */}
      </Suspense>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);

Ovaj pristup omogućuje da svaka aplikacija živi na vlastitom portu (ili domeni), ima vlastiti build proces, ali dijeli zajedničke ovisnosti (React, ReactDOM) kako bi se smanjila veličina bundle-a i poboljšale performanse. Komunikacija bi se mogla odvijati putem globalnog event busa ili context API-ja proslijeđenog kao prop.

Zaključak

Mikrofrontendi nude snažno rješenje za izazove s kojima se suočavaju veliki frontend projekti. Omogućuju veću agilnost, skalabilnost i neovisnost timova, što u konačnici dovodi do bržeg isporučivanja vrijednosti korisnicima. Međutim, nisu srebrni metak. Zahtijevaju značajna ulaganja u arhitekturu, alate, procese i, ključno, u sposobnost timova da rade autonomno uz održavanje konzistentnog korisničkog iskustva.

Ključ uspjeha leži u odabiru pravog arhitektonskog patterna za vaše specifične potrebe, pažljivom rješavanju problema komunikacije i dijeljenja stanja, te strogoj implementaciji dizajnerskog sustava. Ispravno primijenjeni, mikrofrontendi mogu transformirati način na koji razvijate i održavate složene web aplikacije, otvarajući put inovacijama i ubrzanom razvoju.

Izvori i dodatno čitanje

  1. Martin Fowler - Micro Frontends
  2. Webpack - Module Federation
  3. Single-SPA Documentation
  4. ThoughtWorks Technology Radar - Micro Frontends
B
Uredništvo portala

BAJT

Službeni autorski profil redakcije portala BAJT. Sadržaj priprema i provjerava uredništvo portala.