Da macro a micro…tutto!

I micro-frontends, in teoria

Davide D'Antonio
weBeetle
15 min readOct 19, 2020

--

Da sviluppatore ho lavorato su molti progetti software negli ultimi anni. Una delle cose più belle è quando su un progetto appena iniziato ci lavorano poche persone. È bello perché tutti hanno una panoramica completa delle funzionalità e queste vengono sviluppate anche rapidamente. Discutere dei problemi che hai al daily meeting è semplice e veloce! Puoi farlo addirittura mentre sei alla macchinetta del caffè!

Questa condizione idilliaca cambia quando l’ambito del progetto e le dimensioni del team aumentano. Improvvisamente i membri del team non sono più a conoscenza di tutti i limiti del software. Modificare una funzionalità potrebbe avere degli impatti su altre funzionalità. Da qui si evince facilmente che l’aggiunta di nuovi sviluppatori ad un team non per forza aumenta la produttività.

L’avvento delle micro architetture non ha rivoluzionato il modo in cui un’azienda lavora, ma ne ha permeato i processi decisionali, la struttura fino ad arrivare alla comunicazione. L’idea alla base di questo mondo “micro” è quello di pensare a un sito Web o a un’app Web come una composizione di funzionalità che appartengono a team indipendenti. Ogni team ha una distinta area di attività, o missione, a cui tiene e in cui è specializzato. Un team è interfunzionale e sviluppa le sue caratteristiche end-to-end, dal database all’interfaccia utente.

L’approccio a microservizi

La suddivisione del software in micro servizi, ha aiutato notevolmente lo sviluppo. Infatti, utilizzando questo approccio è stato possibile fare due suddivisioni del famoso monolite: la prima, è quella che suddivide orizzontalmente il software tra backend (e quindi l’API) ed il frontend (di solito una Single Page Application). La seconda suddivisione è verticale. L’API backend è stata suddivisa in micro servizi a cui accediamo attraverso uno o più API Gateway. Questo schema architetturale ha scosso notevolmente il modo in cui le risorse vengono distribuite. Un gruppo di persone all’interno del team di sviluppo si occupa, ad esempio, dello sviluppo dell’API di autenticazione e gestione utente, un altro team si occupa della gestione della gestione dei ticket di supporto e così via. Quanto appena detto possiamo rappresentarlo schematicamente nel modo seguente:

Approccio a microservizi

Questo approccio tende quindi alla realizzazione di una singola applicazione composta da n servizi sviluppati ed implementati in modo indipendente, secondo il Principio di Singola Responsabilità (Single Responsability Principle — SRP). Infatti ogni servizio è responsabile della persistenza dei propri dati, può differire in termini di tecnologia rispetto agli altri micro servizi, e può essere sviluppato e distribuito in modo indipendente rispetto agli altri.

In questo caso quello che si tende a fare, lato frontend, è cercare di ottimizzare il codice aumentando il numero di persone che ci lavorano, senza tener presente delle complessità, e soprattutto delle problematiche, a cui si va incontro quando aumenti il numero dei componenti di un team che lavorano sullo stesso codice. Infatti uno dei più recenti studi sulle architetture software

Qualsiasi organizzazione che progetta un sistema produrrà inevitabilmente un progetto la cui struttura è una copia della struttura della comunicazione dell’organizzazione.

Melvin Conway

conferma che c’è una stretta correlazione tra l’architettura del software e la comunicazione e la strutturazione in team di un’azienda.

L’approccio a Micro-frontends

I micro-frontends non fanno altro che estendere il concetto dei microservizi allo sviluppo delle interfacce utente. Di conseguenza, dividiamo verticalmente il software ed i gruppi partendo dal database fino ad arrivare all’interfaccia. Questo implica che non esisterà più un team centrale che lavora sul frontend ma diversi gruppi del team che si occuperanno di sezioni diverse dell’applicazione. Questo approccio è fondamentale per due motivi principali:

  • Ottimizza lo sviluppo di funzionalità: un team include tutte le competenze per sviluppare una funzionalità. Non è necessario il coordinamento tra team separati di frontend e backend.
  • Semplifica gli aggiornamenti del frontend: ogni team possiede il proprio stack di competenze completo dal frontend al database; di conseguenza, è quest’ultimo che decide di aggiornare o cambiare la propria tecnologia di frontend (o di backend) in modo indipendente.
Approccio a micro-frontends

Vantaggi

Considerato l’alto grado si similitudine tra microservizi e micro-frontends, i sostenitori dei micro-frontends stanno evidenziando i vantaggi dell’organizzazione derivanti dalla riduzione delle dipendenze tra i team. Alcuni dei vantaggi dei micro-frontends includono:

  • Distribuzioni separate per servizi separati.
  • Capacità di team autonomi di iterare e innovare in modo indipendente.
  • Capacità di organizzare i team attorno a unità o prodotti aziendali.

Tutti questi sono vantaggi validi, soprattutto per progetti grandi e complessi, ma anche le applicazioni più piccole possono trarre vantaggio da cose come le distribuzioni indipendenti.

Svantaggi

Ad oggi avere un ambiente front-end funzionante è difficile, poiché siamo passati dalla modifica di file statici a sistemi di compilazione complessi, transpilation e framework di grandi dimensioni. I micro-frontends complicano ulteriormente la situazione dove eseguire i test sull’intera applicazione potrebbe richiedere più frontend di coordinamento; per non parlare degli strumenti utilizzati per fonderli insieme!

Le sfide possono essere familiari ai programmatori che sviluppano microservizi:

  • Necessità di avere molte applicazioni diverse in esecuzione in fase di sviluppo per testare un’esperienza completa.
  • Monitoraggio e debug dei problemi nell’intero sistema.
  • Gestire il controllo delle versioni in tutto il sistema.

Essenzialmente stiamo scambiando la semplicità all’interno di un singolo frontend con la complessità nel sistema generale.

Ulteriori problematiche a cui si va incontro

Oltre agli svantaggi elencati in precedenza bisogna tener conto anche delle seguenti problematiche:

  • Visto che ogni team fa la propria scelta tecnologica, potremmo scaricare più volte lo stesso framework (per esempio React).
  • Gli utenti non sperimentano la tua azienda o il tuo prodotto in modo isolato.
  • Alcune delle implementazioni di micro-frontend (in particolare gli iframe) possono causare enormi problemi di accessibilità.

Ma cosa sono i micro-frontends?

Se ricercate in rete, o tra i libri attualmente in giro troverete diverse definizioni. La definizione “classica” è:

Micro-frontend architecture is an approach to developing web application as a composition of small front-end apps.

Ma quella che preferisco, e la più esaustiva secondo me, è quella di Luca Mezzalira (Vice President of Architecture in DAZN) che definisce i micro-frontends nel modo seguente:

Micro-frontends are the technical representation of a business subdomain (from Domain Driven Design DDD), they allow independent implementations with same or different technology choices.

Finally they should avoid sharing logic with other subdomains and they are own by a single team.

Luca Mezzalira

Analizzando la definizione di Luca Mezzalira per punti:

I micro-frontends sono la rappresentazione tecnica di un sottodominio. Se prendiamo, ad esempio, una piattaforma di streaming come DAZN dove appunto il dominio principale è quello di poter effettuare lo streaming di contenuti multimediali. Ci sono tutta una serie di sottodomini che sono legati a quello principale, ma che allo stesso tempo possono essere scissi da quest’ultimo. Nell’esempio di DAZN, potrebbe essere quella del metodo di pagamento, che può essere lo stesso che magari possiamo utilizzare su una piattaforma di shop online. Ragionando in questo modo possiamo dire che esiste il dominio principale, che è quello specifico per la piattaforma in questione, ma altri che possono essere generici se vogliamo. Investire tempo all’inizio di un progetto per identificare i diversi sottodomini e come suddividere l’applicazione è molto utile quando si aggiungeranno in seguito nuove funzionalità.

I micro-frontends consentono implementazioni indipendenti con scelte tecnologiche uguali o differenti. Questo punto è molto importante soprattutto se a lavorare sul frontend ci sono diversi team. Il team che si occupa del metodo di pagamento lavora in modo del tutto indipendente e con il framework (React, Angular, Vue etc. o quelli scelti in modo condiviso all’interno di un’azienda) che ritiene più opportuno utilizzare, rispetto al team che si occupa della landing page, del player multimediale, oppure della pagina dei prodotti che la piattaforma mette a disposizione.

I micro-frontends dovrebbero evitare di condividere la logica con altri sottodomini e sono di proprietà di un unico team. Nel momento in cui ogni team è owner di uno specifico dominio, deve cercare di evitare di condividere la propria logica di business, il proprio codice, con altri micro-frontends.

Principi alla base dei Micro-frontends

I principi ci aiutano a prendere decisioni quando costruiamo i nostri sistemi. Per quanto riguarda i micro-frontends non esistono dei principi chiari e precisi che ci aiutano a scalare un’architettura sul frontend, cosa che invece ha fatto Sam Newman nel suo libro Building Microservices dove spiega i principi guida dei microservizi.

Principi dei micro servizi

Questi sono i principi che ci aiutano a creare piccoli micro servizi autonomi che funzionano bene insieme e possono essere applicati anche ai micro-frontends. Analizziamo i vari punti.

Modellato intorno al business domain

Sam Newman ci dice che se modelliamo il dominio in cui opera il nostro sistema, non solo creeremo interfacce più stabili, ma ci assicuriamo anche di essere in grado di riflettere meglio i cambiamenti nei processi aziendali. Quello che si tende a fare, lato frontend, è quello di utilizzare lo stesso approccio cercando di capire come un’interfaccia possa essere scomposta e guardandolo dal punto di vista di come gli utenti utilizzano le funzionalità del vostro sistema, quindi in pratica analizzando i dati della vostra applicazione.

La faccenda si complica quando il progetto è nuovo e, di conseguenza, dovete sforzarvi a fare assunzioni che non hanno un riscontro sui dati.

Decentralizzazione

Così come per l’approccio a microservizi, il team è libero di utilizzare lo strumento più adatto rispetto al dominio in cui sta operando in piena autonomia. Figure come il CTO non si preoccupano più di prendere tutte le decisioni riguardanti lo sviluppo di un’intera piattaforma, imponendole di conseguenza ai team di sviluppo.

Cultura dell’automazione

Così come i microservizi anche i micro-frontends non possono esimersi dall’avere un investimento sia in termini di tempo che in termini economici sulla parte dell’automazione. Senza ciò l’approccio ai micro-frontends rischia di diventare un incubo per tutti i team di sviluppo. Investire tempo e denaro per ottenere la giusta automazione si tradurrà in un’adozione più regolare dei mirco-frontends.

Isolare i fallimenti

Se immaginiamo di avere una pagina che contiene diversi micro-frontends, e alcuni di questi causano errori, può diventare un problema dal punto di vista dell’esperienza utente. A causa di un singolo micro-frontend l’utente potrebbe trovarsi davanti ad una pagina con errori incomprensibili. È necessario gestire questi errori in modo da fornire sempre la migliore esperienza utente.

Osservabile

Esattamente come per i microservizi non possiamo fare affidamento all’osservazione del singolo servizio per vedere se l’intero sistema sta funzionando correttamente. A tal proposito, infatti, esistono tool per il monitoring dell’intera applicazione come LogRockets o Sentry che sono indispensabili per capire se la nostra applicazione va in errore e perché.

Deploy Indipendente

L’approccio ai micro-frontends, esattamente come i microservizi, aiuta i team ad essere autonomi anche da questo punto di vista. Non bisogna aspettare che dipendenze esterne vengano risolte prima di effettuare un deploy.

Nascondere i dettagli di implementazione

Nascondere i dettagli di implementazione e lavorare con degli accordi sono due pratiche essenziali, soprattutto quando parti della nostra applicazione devono comunicare tra loro. È fondamentale definire in anticipo delle regole tra i team e che tutte le parti le rispettino durante l’intero processo di sviluppo. In questo modo ogni team sarà in grado di effettuare modifiche senza influire sul lavoro di altri team a meno che non vi sia una modifica di tali regole.

Decision framework

Quando si imposta un progetto basato sui micro-frontends con team diversi, bisogna prendere alcune decisioni in anticipo. Queste decisioni vanno dalla definizione dei micro-frontends (ossia come verranno strutturate le interfacce) fino al come questi comunicheranno fra di loro. Luca Mezzalira definisce questa serie di decisioni con il nome di Micro-frontends Decision Framework che si suddividono in quattro aree decisionali:

  • Definizione. Definire cos’è il micro-frontend nella tua architettura.
  • Composizione. Come i diversi micro-frontend verranno composti fra di loro.
  • Routing. Come verrà gestito il routing tra i micro-frontends; in sostanza come facciamo a muoverci da un micro-frontend all’altro.
  • Comunicazione. Come i micro-frontends comunicheranno fra loro.

Definizione

La definizione è la decisione più importante, in quanto con questa definiamo come andremo a strutturare i micro-frontends dal punto di vista tecnico. In parole povere: andremo a definire se verranno visualizzati più micro-frontends sulla stessa pagina oppure se un solo micro-frontend alla volta.

Nel primo caso, stiamo dividendo l’interfaccia utente in modo orizzontale.

Suddivisione Orizzontale

Questo approccio richiede un effort maggiore per quanto riguarda il coordinamento dei team, sia in fase di sviluppo che di progettazione, e allo stesso tempo ci consente di utilizzare lo stesso micro-frontend su più interfacce.

Nel secondo caso invece, stiamo dividendo l’interfaccia in modo verticale.

Suddivisione Verticale

Con la suddivisione verticale, ogni team sarà responsabile di un’ intera interfaccia. Questa approccio risulta molto utile soprattutto quando un team è responsabile end to end (quindi dall’interfaccia al database, passando per i microservizi) di un dominio di business come ad esempio l’autenticazione, il catalogo prodotti etc.

Composizione

Come già anticipato in precedenza, la composizione riguarda il come i micro-frontends verranno serviti al client. Esistono tre diverse metodologie di composizione:

  • Client Side Composition
  • Server Side Composition
  • Edge Side Composition

Client Side Composition

Client side composition

In questo caso la composizione dei vari micro-frontend avviene nel browser e viene fatta da un’application shell. Ognuno di questi micro-fronted ovviamente sarà agnostico rispetto alla tecnologia utilizzata e verrà caricato dinamicamente all’interno dell’application shell attraverso un loader.

Server Side Composition

Server Side Composition

Il vantaggio più significativo dell’integrazione, lato server, è che la pagina è già completamente assemblata quando raggiunge il browser. Se il micro-frontend è statico si può adottare una strategia di caching a lungo termine mentre, in caso contrario, sarà necessaria una seria considerazione riguardo la scalabilità dell’eventuale soluzione, quando ci sono molte richieste provenienti da client diversi.

Edge Side composition

Edge Side Composition

Molti providers forniscono servizi per far si che questa tipologia di composizione possa avvenire a livello di CDN. Questa è basata su una specifica denominata Edge Side Inclusion (ESI) che definisce uno standard per assemblare markup. Providers come Akamai e server proxy come Varnish, Squid e Mongrel supportano ESI. Un esempio di markup ESI ha un aspetto del genere:

Routing

Questa decisione spesso si basa sulla scelta fatta in precedenza e anch’essa può essere di tre tipi:

  • Client Side Routing
  • Server Side Routing
  • Edge Side Routing

Client Side Routing

Client Side Routing

In questa tipologia di routing viene demandato solitamente all’application shell. Infatti, se questa utilizza un framework moderno come Angular allora il routing possiamo effettuarlo con @angular/router , o nel caso di un’applicazione React possiamo fare routing con react-router-dom e così via. Esistono anche diversi framework come Single-SPA che si occupano anche del routing tra micro-frontends. Questo approccio è molto utile quando abbiamo un routing molto complesso.

Server Side Routing

Server Side Routing

In questo approccio, l’intera logica dell’applicazione risiede lato server. Esistono diversi framework che si occupano di questo aspetto come Podium, che fornisce plugins per i maggiori framework nodejs come express o fastify.

Edge Side Routing

Edge Side Routing

Quando decidiamo di utilizzare la composizione edge-side nella nostra architettura, il routing è basato sull’URL della pagina e la CDN serve la pagina richiesta assemblando i micro-frontend a questo livello.

Comunicazione

Uno dei problemi quando si approccia alle architetture a micro-frontends è come questi dovranno comunicare fra di loro. In generale, è sconsigliato far comunicare i micro-frontends, in virtù dei principi elencati in precedenza. Ma nonostante questo, spesso è necessario un certo livello di comunicazione tra i micro-frontends.

Bus di comunicazione condiviso: viene istanziato nell’application shell, e iniettato all’interno dei micro-frontends che compongono la nostra interfaccia e quando uno di questi è interessato all’evento che si è verificato reagisce di conseguenza. Questa metodologia riduce molto l’accoppiamento ma richiede un sforzo maggiore da parte dei diversi team coinvolti in fase di definizione dell’API di comunicazione.

URLs: un’altra alternativa è usare la barra degli indirizzi come meccanismo di comunicazione con l’opportuna query string. Ovviamente non è il modo più sicuro per passare dati sensibili, come id o password.

Storage: ancora un’altra metodologia che potete utilizzare per la comunicazione tra un micro-frontends e l’altro è quella di utilizzare il localStorage (o simili) o i cookies. In questo modo un micro-frontend conserva delle informazioni ed un altro ne usufruisce.

Aziende che utilizzano i Micro-frontends

Ecco 7 organizzazioni che stanno utilizzando con successo micro-frontends.

DAZN

DAZN è un servizio di streaming sportivo fondato in Europa ma che si è espanso in nove paesi in tutto il mondo. Luca Mezzalira, che è il Chief Architect di DAZN, è stato uno dei principali sostenitori dei micro-frontends e ha prodotto una serie di risorse che spiegano sia perché i micro-frontends sono utili sia come le organizzazioni possono implementarli.

I micro-frontends hanno permesso a DAZN di potenziare i team più piccoli che possono lavorare in modo indipendente. I micro-frontends servono a creare il tipo di decentralizzazione che le organizzazioni più grandi devono impiegare per mantenere la velocità sul mercato.

Molti dei concetti su cui si basa quest’articolo provengono dall’esperienza e dalle risorse che Luca Mezzalira mette a disposizione in rete (link in bibliografia).

IKEA

L’azienda europea di mobili (che è quasi ugualmente famosa per servire le polpette svedesi nella sua food court) utilizza micro-frontends per la loro esperienza di negozio online.

Upwork

La piattaforma freelance per i professionisti aziendali indipendenti per connettersi e collaborare è passata a un’architettura micro-frontends nel 2017, come parte di uno sforzo globale per modernizzare la loro esperienza utente.

Spotify

Spotify, il servizio di streaming multimediale online, utilizza micro-frontends per le loro applicazioni desktop e utilizza iframe per assemblare l’applicazione insieme.

SoundCloud

Anche SoundCloud, la piattaforma europea di distribuzione audio online e sito di condivisione di musica, ha visto i propri team trarre vantaggio dall’utilizzo di micro-frontends.

HelloFresh

HelloFresh è un’azienda internazionale di kit per pasti con sede a Berlino, in Germania, e funge da più grande fornitore di kit per pasti negli Stati Uniti. E i loro team di sviluppo sono stati in grado di superare le barriere all’innovazione rompendo il monolite front-end.

Zalando

Zalando è una società di e-commerce con sede in Germania. Tuttavia, fanno di più che vendere prodotti online. Oltre all’e-commerce, l’azienda è a capo anche di Project Mosaic, che è un insieme di servizi e librerie che supportano un’architettura in stile micro-frontends per grandi siti web, fornendo un contributo significativo a questo metodo di sviluppo frontend.

Frameworks

Esistono diverse soluzioni da adottare per iniziare a sviluppare applicazioni utilizzando i micro-frontends. Se volete utilizzare un approccio client-side Luca ci consiglia:

mentre server-side abbiamo i seguenti:

Concludendo

In questo primo articolo abbiamo fatto una brevissima introduzione ai concetti che ci sono alla base dei micro-frontends. Abbiamo visto quali sono le decisioni da prendere per iniziare a progettare le nostre future applicazioni che utilizzeranno questo approccio. Tante sono le scelte da effettuare così come tanti sono i framework che possiamo utilizzare. Nel prossimo articolo (o nei prossimi) costruiremo l’interfaccia della nostra applicazione di ticketing, per quanto riguarda i microservizi, utilizzando ovviamente i micro-frontends (in particolare i Moduli Federati di Webpack 5) di cui abbiamo discusso in questo articolo.

Per il momento e solo per il momento…Happy Reading!

Bibliografia e letture consigliate

--

--

Davide D'Antonio
weBeetle

👨‍🎓Degree in computer science 💑 Married with Milena 🤓 Huge Nerd! 💻 Code lover 👨🏻‍💻 Fullstack developer