⚡ Prestazioni web

Idratazione e architettura a isole: meno JavaScript per pagine veloci

Perché le pagine generate dal server ma idratate per intero restano lente, e come idratazione parziale, isole e componenti server riducono il lavoro.

Un sito costruito con un framework JavaScript moderno può essere generato sul server e arrivare al browser come HTML completo: testi, immagini e struttura sono visibili presto, e l'LCP spesso è buono. Eppure, in molti casi, per qualche secondo la pagina non risponde ai clic, i menu non si aprono e i campi non reagiscono. Il responsabile ha un nome preciso: idratazione.

Cos'è l'idratazione

Nel rendering lato server classico di un'applicazione a componenti, il server esegue i componenti e produce HTML. Quell'HTML però è "secco": non ha gestori di evento né stato. Per renderlo interattivo, il browser deve:

  1. scaricare il JavaScript di tutti i componenti della pagina;
  2. eseguirli di nuovo, ricostruendo in memoria la stessa struttura già presente nell'HTML;
  3. collegare i gestori di evento agli elementi esistenti.

Questo processo è l'idratazione. Il punto debole è che lavora sull'intera pagina, anche sulle parti che non hanno nulla di interattivo: il testo di un articolo, il piè di pagina, un elenco statico. Il JavaScript di quei componenti viene comunque inviato ed eseguito, solo per scoprire che non c'è niente da collegare.

Il risultato è un divario tra quando la pagina sembra pronta e quando è pronta. Il tempo speso in idratazione appare come task lunghi sul main thread, che peggiorano l'INP delle prime interazioni.

Quanto della pagina è davvero interattivo

Un esercizio utile è guardare una pagina tipica e segnare le parti che hanno bisogno di JavaScript. In una scheda prodotto, per esempio:

Parte della pagina Interattiva?
Intestazione con logo e link No, salvo il menu mobile
Galleria di immagini Sì
Titolo, prezzo, descrizione No
Selettore di taglia e pulsante carrello Sì
Recensioni No, salvo il pulsante «Mostra altre»
Piè di pagina No

Spesso la parte interattiva è una frazione minoritaria. Idratare tutto significa pagare per l'intera pagina il prezzo che servirebbe solo per alcune zone.

Le alternative

Negli ultimi anni sono nati diversi approcci per ridurre questo lavoro. Non si escludono a vicenda e i nomi variano tra framework.

Idratazione progressiva o differita

I componenti vengono idratati in momenti diversi invece che tutti insieme: subito quelli nella parte visibile, gli altri quando entrano nello schermo, quando il browser è inattivo o al primo contatto dell'utente. Il JavaScript totale non cambia, ma si distribuisce nel tempo e non blocca le prime interazioni.

Architettura a isole

La pagina è considerata HTML statico per impostazione predefinita, e solo alcune zone dichiarate esplicitamente, le isole, ricevono JavaScript e vengono idratate in modo indipendente. Astro ha reso popolare questo modello: un componente diventa interattivo solo se lo si marca come tale, e si può scegliere quando idratarlo.

<Intestazione />
<Galleria client:visible />
<DescrizioneProdotto />
<SelettoreTaglia client:load />
<Recensioni />

In questo esempio solo la galleria e il selettore inviano JavaScript al browser; il resto arriva come semplice HTML.

Componenti lato server

Alcuni framework, come React con i Server Components, distinguono tra componenti che girano solo sul server, il cui codice non viene mai inviato al browser, e componenti client che invece vengono idratati. Il principio è simile alle isole, ma integrato nell'albero dei componenti di un'applicazione.

Ripresa invece di idratazione

Un approccio più radicale, adottato per esempio da Qwik, evita di rieseguire i componenti nel browser: il server serializza nell'HTML lo stato necessario e il codice di un gestore viene scaricato solo quando l'evento corrispondente si verifica. Il lavoro iniziale nel browser diventa minimo.

Come scegliere

La scelta dipende dalla natura del sito più che dalle mode:

  • siti di contenuto (blog, documentazione, siti istituzionali, cataloghi): l'architettura a isole o una generazione statica con poco JavaScript mirato sono quasi sempre la scelta migliore;
  • applicazioni molto interattive (editor, dashboard, strumenti): l'idratazione completa ha più senso, perché gran parte della pagina è davvero interattiva, ma conviene comunque dividere il codice per percorso;
  • siti misti (e-commerce, portali): componenti server o isole permettono di tenere statiche le parti di contenuto e interattive solo quelle che servono.

Nel mio lavoro, migrare un sito di contenuto da un'applicazione interamente idratata a un modello a isole ha spesso ridotto il JavaScript iniziale in modo radicale senza cambiare nulla di visibile per l'utente.

Come misurare il costo attuale

Per capire quanto pesa l'idratazione su un sito esistente:

  1. registra un caricamento nel pannello Performance di DevTools con CPU rallentata e cerca i task lunghi subito dopo il primo disegno: spesso portano il nome delle funzioni di idratazione del framework;
  2. confronta il momento dell'LCP con quello in cui il main thread si libera;
  3. guarda nel pannello Coverage quanta parte del JavaScript scaricato viene eseguita per costruire componenti non interattivi;
  4. controlla nei dati reali se l'INP delle prime interazioni è peggiore di quello delle successive.

In sintesi

  • L'idratazione riesegue nel browser i componenti già resi dal server per renderli interattivi.
  • Idratare l'intera pagina spreca lavoro sulle parti statiche e ritarda le prime interazioni.
  • Idratazione differita, isole, componenti server e ripresa riducono o distribuiscono quel lavoro.
  • I siti di contenuto traggono il massimo beneficio dalle isole e dal poco JavaScript.
  • Misura con il pannello Performance e con l'INP delle prime interazioni.
MM
Marco Marzaduri

Marco Marzaduri si occupa di cybersecurity, informatica forense e sviluppo web. Laureato in informatica, unisce il rigore dell'analisi tecnica all'attenzione per le persone che usano la tecnologia.

Leggi anche