Avvicinandosi a un vero framework
Grande successo per Claudia Bressi (sviluppatrice Frontend di Bitrock) alla Byteconf React 2020, la conferenza annuale online con i migliori relatori e docenti React del mondo.
Durante l’evento, Claudia ha avuto l’opportunità di parlare del suo esperimento chiamato “React Bandersnatch” (il nome deriva da uno degli episodi della serie tv Black Mirror, dove la libertà è rappresentata come una sorta di illusione ben progettata).
L’obiettivo di questo articolo è quello di dare a tutti coloro che non hanno potuto partecipare all’evento virtuale la possibilità di approfondire il suo esperimento e le sue principali scoperte, che rappresentano un contributo di grande valore per l’intera comunità del front-end.
Ecco le parole di Claudia, che descrive il progetto in dettaglio.
“Il progetto parte da una semplice idea: cosa succederebbe se React fosse un framework, invece che una libreria per costruire interfacce utente?
Per questo progetto, ho costruito alcune applicazioni reali utilizzando diversi pacchetti che sono normalmente disponibili all’interno di un tipico framework frontend. Ho misurato le principali metriche delle applicazioni web e ho confrontato i risultati ottenuti.”
Il fulcro dell’esperimento è il concetto di framework, ovvero una piattaforma in cui è possibile trovare componenti e strumenti già pronti che possono essere utilizzati per progettare un’interfaccia utente, senza la necessità di cercare appendici esterne.
Grazie ai framework, è sufficiente aggiungere un codice di configurazione appropriato e si è subito pronti a programmare qualsiasi cosa si voglia implementare. Gli sviluppatori scelgono spesso un framework perché è davvero comodo avere qualcosa di pronto e niente da scegliere.
Confrontate con le librerie, i framework sono più autorevoli: offrono delle regole da seguire e possono fare al posto tuo varie cose dietro le quinte. È il caso del lazy loading quando si ha a che fare con i moduli in una grande applicazione enterprise.
D’altra parte, le librerie sono più minimaliste: forniscono solo il necessario per costruire le applicazioni. Allo stesso tempo, però, si ha più controllo e libertà di scegliere qualsiasi pacchetto al mondo, premurandosi di seguire tutte le best practices per evitare un codice scadente.
Il progetto
Come fase iniziale del mio progetto, ho costruito un’applicazione web molto semplice in React per implementare un’agenda settimanale. Si articolava in un componente che mostrava la settimana, un altro che mostrava i dettagli di un giorno specifico e alcuni pulsanti per aggiornare l’interfaccia utente, ad esempio per aggiungere eventi e riunioni.
Ho utilizzato React (l’ultima versione disponibile) e Typescript (in una versione che consente agli utenti di utilizzare l’optional changing). Per creare lo stile dell’applicazione, ho usato solo file .scss, quindi ho incluso un compilatore Sass – inoltre durante la scrittura dei componenti ho stilizzato questi ultimi utilizzando i CSS modules.
In seguito ho definito un preciso insieme di criteri di misurazione, al fine di poter valutare il framework sperimentale.
Più precisamente:
- dimensione del bundle (misurata in kilobyte, per capire quanto peso si potesse raggiungere con ogni build);
- durata di loading (la quantità di tempo necessaria per caricare il codice HTML nell’applicazione);
- durata di scripting (il tempo effettivo necessario per caricare i file Javascript);
- durata di rendering (il tempo necessario per il rendering dei fogli di stile all’interno del browser);
- durata di painting (il tempo di gestione dei file multimediali, come immagini o video)
I pacchetti utilizzati per questo esperimento possono essere considerati gli ingredienti del progetto. Ho cercato di scegliere sia strumenti noti nello scenario di React, sia alcuni pacchetti forse meno noti, ma con caratteristiche che possono migliorare le prestazioni complessive su progetti di medie dimensioni.
La prima implementazione può essere considerata un modo classico di risolvere un progetto in React. Un’implementazione basata su Redux per la gestione dello stato e su Thunk come soluzione middleware. Ho utilizzato anche il noto React router e, non ultimo, il popolare Material UI per avere alcuni componenti UI pronti all’uso.
La seconda applicazione può essere considerata più sofisticata: è stata realizzata con Redux, combinato con il pacchetto Redux-observable per gestire la parte middleware. Per quanto riguarda il routing, ho applicato una soluzione router personalizzata, in modo da poter giocare di più con gli hook di React. Come ciliegina sulla torta, ho preso la libreria Ant, per costruire alcuni componenti dell’interfaccia utente.
Per quanto riguarda la terza applicazione, ho unito il gestore di stati MobX con il mio precedente router personalizzato basato sugli hook, mentre per la parte dell’interfaccia utente ho utilizzato la libreria Ant.
Infine, per la quarta applicazione sperimentale, ho creato una soluzione piuttosto semplice con MobX, il mio router personalizzato basato su hook (di nuovo) e Material UI per completare il framework complessivo.
Risultati principali
Analizzando queste quattro implementazioni, ho constatato che, come gestore di stati, Redux ha una struttura più pulita e meglio organizzata, grazie al suo paradigma funzionale. Un altro vantaggio è lo store di dati immutabili, che previene ogni possibile incoerenza quando i dati vengono aggiornati.
D’altra parte, MobX consente di avere più store: questo può essere particolarmente utile se si ha la necessità di riutilizzare alcuni dati (ad esempio la parte di business logic del proprio archivio) in un’applicazione diversa, ma simile, con una logica condivisibile.
Un altro vantaggio di MobX è quello di avere un paradigma reattivo che si occupa degli aggiornamenti dei dati, in modo da poter saltare qualsiasi dipendenza dal middleware.
Per quanto riguarda il routing, una soluzione integrata (come il pacchetto react-router-dom) è piuttosto facile e agevole da applicare per impostare tutte le rotte necessarie all’interno dell’applicazione. Una soluzione personalizzata, invece, come la nostra soluzione di router basata sugli hook, ci permette di mantenere il nostro bundle finale più leggero.
Passando al lato UI del framework, possiamo dire che Material UI è un paradigma di stile web molto diffuso: le sue regole sono facili da applicare e il risultato è pulito, ordinato e minimalista.
Tuttavia, dal mio punto di vista personale, non è ottimale inquinare il codice Javascript con il codice CSS: ecco perché ho preferito tenere le cose separate. Ho quindi cercato un’altra libreria per l’interfaccia utente e ho trovato Ant, che è scritta in Typescript con tipi statici prevedibili: un vero vantaggio per le mie applicazioni. Tuttavia, alla fine, possiamo dire che MaterialUI è più leggero di Ant.
In ogni caso, entrambi i pacchetti consentono di importare solo i componenti necessari per il progetto. Quindi, alla fine, è una semplice questione di gusti su quale libreria utilizzare per i componenti dell’interfaccia utente (in ogni caso: se si guarda più alle prestazioni, allora si scelga Material UI).
Confronto dei risultati
Come ultimo passo, ho confrontato i risultati ottenuti per ciascuna delle metriche sopra citate.
Dai risultati raccolti, è abbastanza significativo che l’applicazione più performante sia stata costruita con un bundle di dimensioni ridotte e, in particolare, quando si utilizza Redux accoppiato a Thunk; MaterialUI per i componenti dell’interfaccia utente e il nostro router personalizzato, l’applicazione risultante ha un bundle più piccolo e valori ottimizzati per i tempi di caricamento, scripting e rendering.
In conclusione la soluzione migliore di questo esperimento risulta essere l’applicazione n. 4.
Tuttavia, per progetti di maggiori dimensioni i risultati possono variare.
Plugins ideali
I framework, a volte, offrono utili plugin ausiliari integrati, come la CLI per utilizzare facilmente alcuni comandi o automatizzare attività ripetitive, che a loro volta possono migliorare la vita degli sviluppatori. Ecco perché alcuni dei miei strumenti preferiti disponibili per React (che includerei in uno scenario ideale di framework React) sono:
- le famose estensioni React e Redux per Chrome: le ho trovate essenziali e utili come il righello di un architetto;
- il plugin ‘eslint’ scritto appositamente per React, che rende più facile essere coerenti con le regole che si vogliono mantenere nel codice;
-Prettier, un altro plugin per React indispensabile se si usa VS Code, che aiuta molto a ottenere un codice formattato meglio;
-React Sign, un’estensione di Chrome che vi aiuta a mostrare un grafico e a rappresentare la struttura complessiva per analizzare i vostri componenti;
– Il popolare plugin di VS Code “React Extension Pack” che offre molte azioni automatizzate per gli sviluppatori, come centinaia di snippet di codice, Intellisense e l’opzione di ricerca di file all’interno dei moduli dei nodi.
Se vuoi ascoltare il discorso completo di Claudia durante l’evento, fai clic qui e accedi alla registrazione video ufficiale disponibile su YouTube.