Introduzione al Microfrontends e alla Module Federation

In qualità di Software Architect, gestire un’architettura software che si evolve per adattarsi al business nel corso degli anni può essere un compito complesso. All’inizio della sua vita, l’architettura software era a basso livello di scalabilità e poteva essere gestita da un team di Back-End e uno di Front-End, oltre a essere composta da soli tre livelli: Applicazione a pagina singola, Application Server e Database.

Con l’aumento del numero di utenti e di servizi, nasce l’esigenza di un’architettura altamente scalabile. Allo stesso tempo, la vecchia architettura si evolve in Microservizi che rendono la nostra applicazione scalabile in termini di sviluppo. Infatti, ogni microservizio viene assegnato a diversi team di back-end incaricati di gestirlo, con il vantaggio di poter scegliere e adottare release e tecnologie autonome. In questa fase, l’architettura è pronta per aggiungere nuove funzionalità, mentre per il team Front-End è difficile gestirla risparmiando tempo e lavoro. 

È qui che entrano in gioco i Microfrontend. Ma cosa sono esattamente gli MFE?

Gli MFE sono una rappresentazione tecnica e logica di un sottodominio aziendale in Domain-Driven Design (DDD) che consente lo sviluppo e il rilascio indipendente di parti dell’applicazione. Questo approccio evita la condivisione della logica tra i sottodomini e consente la gestione da parte di un unico team.

Un concetto molto importante per l’applicazione di questo approccio è che la nostra architettura è guidata dal dominio e non viceversa, quindi i nostri MFE rappresenteranno un preciso sottodominio. Ogni sottodominio sarà sviluppato da un singolo team che sarà libero di scegliere la tecnologia e la metodologia giusta per implementare e gestire le funzionalità. Per garantire una buona gestione del lavoro dei team, è importante progettare un’architettura con un accoppiamento molto basso tra i Microfrontend (MFE). Questo approccio consente esperienze di sviluppo e rilascio indipendenti.

Ma come possiamo applicare l’architettura e le MFE? È fondamentale considerare il contesto specifico in cui si lavora. Come sempre, il dominio aziendale avrà un ruolo significativo nel guidare le decisioni architetturali. I problemi chiave da affrontare saranno i seguenti: definizione; composizione e instradamento; comunicazione.

Definizione

Esistono due tecniche per definire e implementare efficacemente l’architettura Microfrontends (MFE): La suddivisione orizzontale e la suddivisione verticale. Analizziamo ciascuna tecnica:

  • Nel Horizontal splitting, più MFE sono ospitati all’interno di una singola vista dell’applicazione. Ad esempio, una home page può essere composta da MFE quali piè di pagina, intestazione, anteprima dell’articolo ed elenco degli articoli. La sfida principale di questo approccio consiste nel garantire che i team possano creare un look and feel coeso basato su un design di sistema comune. Tuttavia, c’è il rischio di creare componenti fortemente accoppiati, che possono deviare dagli MFE definiti dall’azienda.
  • Nel Vertical Splitting, l’applicazione viene suddivisa in unità logiche basate sui sottodomini di business. Ad esempio, possono esserci MFE separate per la pagina di login, la home page e la pagina del catalogo, ciascuna progettata come se fosse una Single Page Application (SPA) separata. Questa tecnica consente ai team di avere una conoscenza approfondita di un sottodominio e facilita l’implementazione della progettazione del sistema.

Composizione e instradamento

La composizione e l’instradamento sono aspetti critici dell’implementazione dell’architettura Microfrontends (MFE). Esistono tre tecniche che possono essere utilizzate per comporre le MFE e gestire l’instradamento:

  • Composizione lato client: La shell dell’applicazione è responsabile della fusione delle MFE e della gestione dell’instradamento tra di esse. La composizione può essere effettuata in fase di esecuzione o di creazione.
  • Composizione lato CDN: L’applicazione viene composta sul nodo più vicino all’utente che l’ha richiesta, utilizzando un linguaggio di markup edge-side. Ciò comporta una maggiore scalabilità e tempi di attesa più brevi. L’instradamento è gestito a questo livello tramite gli url per passare da una pagina all’altra.
  • Lato origine: L’applicazione è composta utilizzando il rendering lato server, con il routing sempre gestito lato server.

Comunicazione

Nel ciclo di vita di un MFE, arriva un momento in cui è necessaria la comunicazione. Ad esempio, un MFE può avere bisogno di comunicare che un utente è connesso o di far eseguire azioni ad altri MFE. Le tecniche di comunicazione più comuni sono:

  • Condivisione di dati tramite archiviazione locale (come un token JWT)
  • Passaggio di parametri tramite stringa di query URL
  • Passaggio di parametri tramite eventi (meccanismo di subscribe, emit e replay).

È importante scegliere la tecnica di comunicazione appropriata in base alle esigenze e ai requisiti specifici dell’applicazione.

Che cos’è una Module Federation?

Module Federation è un potente plugin introdotto da Webpack nella versione 5.0, rilasciata nel 2020. Consente lo sviluppo separato di moduli remoti, permettendo la creazione di un’unica applicazione con facilità. Questo plugin facilita l’implementazione di un’architettura basata sull’approccio Microfrontends.

Immaginiamo che il nostro business di riferimento sia un sito di e-commerce. Dopo un’attenta analisi, identifichiamo tre entità che possono essere designate come MFE: l’elenco dei prodotti, il carrello e potenzialmente altri componenti. La responsabilità dell’implementazione di queste MFE viene assegnata a team separati. Una volta completato lo sviluppo degli MFE, i team configurano Webpack per rendere disponibili i moduli remoti. 

productsTeam/webpack.config.js

Microfrontends_1

cartTeam/webpack.config.js

Microfrontends_2

Fondamentalmente, per i moduli esportati il plugin Module Federation espone tre proprietà:

  • Name, che descrive il nome del modulo.
  • Filename, per impostazione predefinita, si chiama remoteEntry.js. Questo file funge da manifest e fornisce tutte le indicazioni necessarie per importare il modulo remoto, compresi il nome del modulo, gli alias, le dipendenze e i riferimenti ai bundle. Viene generato quando il modulo remoto viene compilato e chi lo usa può importarlo usando il suo URL.
  • Exposes o una proprietà che consente di esplicitare i percorsi per raggiungere le funzionalità esposte dal modulo.

Vediamo ora come il team responsabile dell’app-shell importerà i moduli per fonderli in un’unica applicazione. Innanzitutto, dobbiamo chiarire che cos’è un’app-shell. Fondamentalmente, può essere definita come un container di moduli remoti in cui avviene parte dell’implementazione delle basi di MFE. 

Nella composizione lato client, l’app-shell ha la responsabilità non solo di comporre l’applicazione, ma anche di fornire gli strumenti che consentono all’MFE di comunicare e gestire il routing. Con la corretta implementazione dei moduli, ma soprattutto dell’app-shell, possiamo avere un’architettura che si avvicina di più all’ideale teorico dei MFE, ovvero basso accoppiamento, separazione e decentralizzazione dei moduli gestiti da team separati.

app-shell/webpack.config.js

Microfrontends_3

La configurazione del plugin Module Federation per la nostra app-shell presenta alcune differenze. Poiché la funzione dell’app-shell è quella di importare, piuttosto che di esportare, usiamo la proprietà “remotes” per questo scopo. Questa proprietà definisce dove possiamo trovare il file remoteEntry.js che i moduli remoti espongono. La struttura è semplice: usiamo il nome del modulo remoto come chiave (ad esempio, “products” o “cart”) e poi indichiamo il nome del modulo con il simbolo “@” seguito dall’URL. In questo modo, il nostro bundle app-shell conterrà tutte le informazioni necessarie per unire i nostri moduli e creare la nostra applicazione.

Conclusioni

In conclusione, il plugin Module Federation di Webpack 5 ha rivoluzionato l’architettura del software, consentendo il caricamento dinamico del codice e la condivisione delle dipendenze tra applicazioni diverse. Sfruttando questo plugin e configurando correttamente l’app-shell, possiamo ottenere un’architettura che si avvicina all’ideale teorico delle MFE, con basso accoppiamento, separazione e decentralizzazione dei moduli gestiti da team separati.

È importante notare che questo approccio è relativamente nuovo. La comunità è attivamente coinvolta e vengono creati nuovi framework per semplificare il processo di implementazione. Anche altri bundler, come Vite, forniscono plugin agli sviluppatori, con alcune differenze rispetto a Webpack.

È fondamentale ribadire che questo approccio dovrebbe essere adottato solo se è in linea con i requisiti del dominio. Se i potenziali problemi superano i benefici, potrebbe non essere la scelta giusta. Attualmente, grandi aziende tecnologiche come Dazn, Facebook e Zalando utilizzano questo approccio, tenendo conto dei principi di base degli MFE e applicando soluzioni uniche per garantire un’esperienza utente ottimale e un’elevata scalabilità.


Autore: Marco Bartiromo, Frontend Developer @ Bitrock

Vuoi saperne di più sui nostri servizi? Compila il modulo e fissa un incontro con il nostro team!

Skip to content