Best practices e ottimizzazione di React

Ottimizzare React in azienda: cosa abbiamo imparato da un gruppo di lavoro interno
Ci sono due momenti in cui un progetto React ti presenta il conto.
Il primo è quando l’app cresce e inizi a vedere piccoli rallentamenti, rendering “strani”, componenti che fanno più lavoro del necessario. Il secondo è quando cresce il team e ti accorgi che ogni nuova feature arriva con una variazione sul tema: pattern diversi, librerie diverse, convenzioni diverse. Il codice funziona, certo. Ma l’onboarding è lento e ogni scelta va discussa da capo.
Nel nostro caso, a un certo punto ci siamo detti una cosa molto poco eroica ma estremamente utile: invece di inseguire l’ottimizzazione come una caccia al micro-benchmark, proviamo a mettere ordine. E farlo in modo condiviso.
Così è nato un gruppo di lavoro (GdL) interno su best practice e ottimizzazione React, con un obiettivo chiaro: produrre un vademecum di linee guida per chi sviluppa, più qualche pezzo riusabile (un boilerplate, una comparazione sul bundling, una prova concreta del React Compiler).
L’idea di fondo: le performance non si ottengono “ottimizzando”, ma usando bene React
Il punto da cui siamo partiti è quasi banale: le performance “di base” in React arrivano soprattutto dal non abusare del suo lifecycle.
Molti problemi che chiamiamo “React è lento” in realtà sono “stiamo facendo render inutili” o “abbiamo messo lo stato nel posto sbagliato”. E soprattutto: quando un team cresce, questi errori non rimangono isolati. Si replicano. Diventano stile.
Quindi sì, nel vademecum c’è useMemo, c’è useCallback, c’è la lista delle librerie consigliate. Ma il focus vero è un altro: rendere sostenibile il modo in cui costruiamo app React, così che funzionino oggi e restino manutenibili tra sei mesi.
Come abbiamo lavorato: cinque incontri, sottogruppi e un documento non breve
Il gruppo si è riunito cinque volte. All’inizio abbiamo fatto quello che fanno tutti quando vogliono essere efficienti: brainstorming e raccolta dei problemi ricorrenti.
Da lì abbiamo scelto i punti su cui valeva la pena investire:
- gestione dello stato e impatto sui render,
- memoization (sì, ma con criterio),
- scelta delle librerie “standard” per evitare di reinventare tutto,
- boilerplate per partire più veloci,
- e una prova sul React Compiler, perché era impossibile ignorare la tentazione.
Il risultato è stato un vademecum abbastanza corposo (circa 40 pagine), organizzato in modo che non serva leggerlo tutto: si può usare come riferimento quando bisogna prendere una decisione in un progetto.
E soprattutto: non è nato per essere una “Bibbia”. È una base condivisa da cui partire, ma da migliorare in futuro.
Dove nasce il caos: lo stato (e l’arte di causare render senza volerlo)
Se dovessimo scegliere un’unica area che crea problemi nei progetti React, sarebbe questa: lo stato.
Non perché sia difficile usare useState. Ma perché è facile fare scelte che sembrano innocue e poi diventano pesanti:
- spostare in globale ciò che potrebbe restare locale,
- condividere stato senza un criterio chiaro,
- aggiornare più del necessario,
- far propagare refresh in metà applicazione perché “tanto funziona”.
Nel vademecum abbiamo provato a rendere esplicito un concetto: dove metti lo stato determina quanto spesso renderizzi e quanto costa farlo.
Per questo il materiale aiuta a ragionare su:
- quando lo stato locale è la scelta migliore (molto più spesso di quanto si pensi),
- quando serve uno stato condiviso,
- e come orientarsi tra opzioni come Context, Reducer, Redux, Zustand.
L’obiettivo non è “scegli sempre X”. È avere una traccia mentale ripetibile per non finire ogni volta a discutere da zero la stessa cosa.
Memoization: useMemo e useCallback non sono talismani
A questo punto arriva la parte che molti associano all’ottimizzazione: memoization.
useMemo e useCallback sono strumenti utili, ma è anche vero che vengono spesso usati in due modi poco felici:
- ovunque, “così siamo sicuri”,
- mai, “tanto è prematuro”.
In realtà sono scelte che hanno senso quando sai cosa stai facendo. Perché anche la memoization ha un costo: complessità del codice, dipendenze da gestire, rischio di ottimizzare ciò che non serve.
Il vademecum prova a spostare la discussione da “mettiamolo o no” a “perché lo stiamo mettendo”:
- stiamo evitando un calcolo davvero costoso?
- stiamo stabilizzando riferimenti per ridurre render a cascata?
- abbiamo evidenza che quel componente viene renderizzato spesso?
Se la risposta è no, spesso la cosa migliore è lasciare il codice semplice.
Librerie consigliate: meno scelte, meno discussioni, più velocità vera
Un altro punto emerso chiaramente è che, nei progetti, perdiamo un sacco di tempo su problemi non “core”: form, validazione, routing, tabelle, i18n, fetch, testing.
Sono problemi reali, ma non sono il prodotto. E soprattutto: ogni volta che scegliamo librerie diverse, aumentiamo la curva di apprendimento e rendiamo più difficile spostarsi tra progetti.
Per questo nel lavoro è uscita una lista di librerie consigliate, non come vincolo ma come riferimento:
- per ridurre la variabilità,
- abbassare il costo di onboarding,
- evitare implementazioni fatte in casa di cose già risolte bene.
È un punto che sembra “organizzativo”, ma ha un impatto diretto sulla qualità e sulla velocità di sviluppo.
Boilerplate minimale: partire bene senza costruire un framework interno (per fortuna)
Tra i risultati concreti c’è anche un boilerplate minimale condiviso su repository Git Develer.
La scelta qui è stata deliberata: minimale significa che ti dà una struttura comune, ma non ti impone decisioni applicative (router, sidebar, layout ecc.). È una base su cui ogni progetto può costruire senza dover ricominciare da zero.
Durante la presentazione è emersa anche una cosa importante: il boilerplate probabilmente sarà “già superato” presto.
Ed è normale. Il valore non è il boilerplate perfetto. Il valore è avere un punto di partenza condiviso che può evolvere, invece di creare dieci inizi diversi in dieci repository diversi.
Webpack vs esbuild: la scelta conservativa che spesso è quella giusta
Sul bundling abbiamo fatto una comparazione tra Webpack ed esbuild.
Esbuild è veloce, moderno, tentatore. Ma quando il contesto è aziendale, le scelte spesso devono considerare anche:
- maturità,
- ecosistema,
- casi limite,
- prevedibilità nel tempo.
Per questo la decisione finale è stata conservativa: restare su Webpack, non perché sia “migliore”, ma perché è più maturo e meno rischioso come standard condiviso.
A volte la miglior ottimizzazione è evitare di introdurre una variabile in più.
React Compiler: promesse interessanti, prova onesta, risultato… inconclusivo
La parte più “esplorativa” del lavoro è stata la prova sul React Compiler, lo strumento che promette di automatizzare memoization (tipo memo, useMemo) e ridurre i re-render.
Qui abbiamo imparato due cose utili.
La prima: il Compiler non è un cerotto. Funziona bene solo se l’app rispetta rigorosamente le regole del lifecycle di React. Quindi non ti salva da un’architettura disordinata, anzi: ti costringe a essere più disciplinato.
La seconda: per valutarlo davvero serve un caso adatto.
Noi lo abbiamo testato su una piccola app in React 18, già abbastanza semplice e senza problemi evidenti di lag. Con React DevTools si vedeva che la memoization veniva applicata anche senza useMemo o useCallback espliciti. Però non abbiamo visto benefici drastici: l’app era probabilmente troppo piccola per far emergere differenze significative.
In più, il Compiler porta con sé requisiti chiari: React moderno, functional components e hooks, niente class components. E il supporto pieno è pensato per React 19, mentre su 17/18 servono dipendenze aggiuntive con comportamento diverso.
Risultato finale? “Prova inconclusiva”.
E va benissimo così, perché un risultato inconclusivo è comunque informazione. Significa: non adottiamo sulla fiducia. Se vogliamo valutarlo, lo facciamo su un caso reale, misurabile, dove c’è un problema concreto.
Il punto non è imporre regole, ma costruire un manuale vivo
Queste linee guida sono obbligatorie o sono solo documentazione?
Sono una base di partenza, non un dogma. L’obiettivo ideale è evolvere verso un manuale standard, ma serve lavoro nel tempo, esempi reali e contributi di chi ha esperienze diverse.
In pratica: il vademecum serve davvero se diventa un documento vivo, aggiornato quando cambiano le tecnologie e quando impariamo qualcosa di nuovo su progetti concreti.
Conclusione: ottimizzare React significa rendere il progetto più prevedibile
Se dovessimo riassumere il senso di questo lavoro in una frase, sarebbe questa: l’ottimizzazione non è un atto finale, è un modo di costruire.
Gestire bene lo stato, evitare render inutili, usare la memoization con criterio, standardizzare scelte non-core, partire da una struttura comune: sono tutte cose poco glamour, ma sono quelle che rendono i progetti più prevedibili e sostenibili.
Poi se arriva anche un bundle più leggero o un rendering più veloce, meglio. Ma la vera ottimizzazione è quella che riduce il caos. E in azienda, ridurre il caos è praticamente un superpotere.
Il team
Ringraziamo tutto il GdL, composto da Alessandro Mamusa, Giuseppe Chiarella, Nadir Sampaoli, Emilio Veloci, Matteo Bonini, Federico La Rovere, Roberto Gianassi, Diego De Angelis e Lorenzo Savini.