Rendering lato client di HTML e interattività

Il rendering dell'HTML con JavaScript è diverso dal rendering dell'HTML inviato dal server e questo può influire sul rendimento. Scopri la differenza in questa guida e cosa puoi fare per preservare le prestazioni di rendering del tuo sito web, in particolare per quanto riguarda le interazioni.

L'analisi e il rendering dell'HTML sono operazioni che i browser svolgono molto bene per impostazione predefinita per i siti web che utilizzano la logica di navigazione integrata del browser, a volte chiamata "caricamenti di pagine tradizionali" o "navigazioni difficili". Questi siti web vengono talvolta chiamati applicazioni multipagina (MPA).

Tuttavia, gli sviluppatori possono aggirare le impostazioni predefinite del browser in base alle esigenze delle loro applicazioni. Questo è certamente il caso dei siti web che utilizzano il pattern di app a pagina singola (APS), che crea dinamicamente parti di HTML/DOM sul client con JavaScript. Il rendering lato client è il nome di questo pattern di progettazione e può influire sull'Interaction to Next Paint (INP) del tuo sito web se il lavoro necessario è eccessivo.

Questa guida ti aiuterà a valutare la differenza tra l'utilizzo di HTML inviato dal server al browser e la sua creazione sul client con JavaScript e in che modo quest'ultimo può comportare una latenza di interazione elevata in momenti cruciali.

In che modo il browser esegue il rendering dell'HTML fornito dal server

Il pattern di navigazione utilizzato nei caricamenti di pagine tradizionali prevede la ricezione di HTML dal server a ogni navigazione. Se inserisci un URL nella barra degli indirizzi del browser o fai clic su un link in un MPA, si verifica la seguente serie di eventi:

  1. Il browser invia una richiesta di navigazione per l'URL fornito.
  2. Il server risponde con HTML in blocchi.

L'ultimo passaggio è fondamentale. È anche una delle ottimizzazioni delle prestazioni più fondamentali nello scambio tra server e browser ed è nota come streaming. Se il server può iniziare a inviare HTML il prima possibile e il browser non attende l'arrivo dell'intera risposta, il browser può elaborare l'HTML a blocchi man mano che arriva.

Uno screenshot dell'analisi dell'HTML inviato dal server visualizzato nel pannello delle prestazioni di Chrome DevTools. Quando il codice HTML viene inviato in streaming, i relativi blocchi vengono elaborati in più attività più brevi e il rendering è incrementale.
Eseguire l'analisi e il rendering dell'HTML fornito dal server come visualizzato nel riquadro Rendimento di Chrome DevTools. Le attività necessarie per analizzare e visualizzare il codice HTML sono suddivise in blocchi.

Come per la maggior parte delle operazioni che avvengono nel browser, l'analisi dell'HTML avviene all'interno delle attività. Quando l'HTML viene trasmesso in streaming dal server al browser, il browser ottimizza l'analisi del codice HTML analizzandolo un po' alla volta man mano che i bit dello stream arrivano a blocchi. Di conseguenza, il browser cede periodicamente il controllo al thread principale dopo l'elaborazione di ogni chunk, il che evita attività lunghe. Ciò significa che durante l'analisi dell'HTML possono verificarsi altri problemi, tra cui il rendering incrementale necessario per presentare una pagina all'utente, nonché l'elaborazione delle interazioni utente che possono verificarsi durante il periodo di avvio cruciale della pagina. Questo approccio si traduce in un punteggio Interaction to Next Paint (INP) migliore per la pagina.

La morale della storia? Quando esegui lo streaming di HTML dal server, ottieni l'analisi e il rendering incrementali dell'HTML e il rendimento automatico al thread principale senza costi. Non è possibile con il rendering lato client.

Come il browser esegue il rendering dell'HTML fornito da JavaScript

Sebbene ogni richiesta di navigazione a una pagina richieda una certa quantità di codice HTML da parte del server, alcuni siti web utilizzano il pattern SPA. Questo approccio prevede spesso che il server fornisca un payload iniziale minimo di HTML, ma poi il client compila l'area dei contenuti principali di una pagina con HTML assemblato dai dati recuperati dal server. Le navigazioni successive, in questo caso a volte chiamate "navigazioni soft", vengono gestite interamente da JavaScript per compilare la pagina con nuovo codice HTML.

Il rendering lato client può verificarsi anche in applicazioni non SPA in casi più limitati in cui l'HTML viene aggiunto dinamicamente al DOM tramite JavaScript.

Esistono alcuni modi comuni per creare HTML o aggiungere elementi al DOM tramite JavaScript:

  1. La proprietà innerHTML consente di impostare i contenuti di un elemento esistente tramite una stringa, che il browser analizza nel DOM.
  2. Il metodo document.createElement ti consente di creare nuovi elementi da aggiungere al DOM senza utilizzare l'analisi HTML del browser.
  3. Il metodo document.write ti consente di scrivere HTML nel documento (che viene analizzato dal browser, proprio come nell'approccio 1). Tuttavia, per diversi motivi, l'utilizzo di document.write è vivamente sconsigliato.
Uno screenshot dell'analisi dell'HTML visualizzato tramite JavaScript nel riquadro Rendimento di Chrome DevTools. Il lavoro viene eseguito in un'unica attività lunga che blocca il thread principale.
Eseguire l'analisi e il rendering di HTML tramite JavaScript sul client, come visualizzato nel riquadro Rendimento di Chrome DevTools. Le attività di analisi e rendering non sono suddivise in blocchi, il che si traduce in un'attività lunga che blocca il thread principale.

Le conseguenze della creazione di HTML/DOM tramite JavaScript lato client possono essere significative:

  • A differenza del codice HTML trasmesso in streaming dal server in risposta a una richiesta di navigazione, le attività JavaScript sul client non vengono suddivise automaticamente in blocchi, il che può comportare attività lunghe che bloccano il thread principale. Ciò significa che l'INP della pagina può essere influenzato negativamente se crei troppi elementi HTML/DOM alla volta sul client.
  • Se il codice HTML viene creato sul client durante l'avvio, le risorse a cui fa riferimento non verranno rilevate dallo scanner di precaricamento del browser. Ciò avrà sicuramente un effetto negativo sul Largest Contentful Paint (LCP) di una pagina. Anche se non si tratta di un problema di prestazioni di runtime (si tratta invece di un problema di ritardo della rete nel recupero di risorse importanti), non vuoi che l'LCP del tuo sito web venga influenzato dall'aggiramento di questa ottimizzazione fondamentale delle prestazioni del browser.

Cosa puoi fare in merito all'impatto sul rendimento del rendering lato client

Se il tuo sito web dipende molto dal rendering lato client e hai notato valori INP scadenti nei dati di campo, potresti chiederti se il rendering lato client abbia qualcosa a che fare con il problema. Ad esempio, se il tuo sito web è un'applicazione SPA, i dati sul campo potrebbero rivelare interazioni responsabili di un notevole lavoro di rendering.

Qualunque sia la causa, ecco alcune potenziali cause che puoi esaminare per tornare alla normalità.

Fornisci il maggior numero possibile di HTML dal server

Come accennato in precedenza, per impostazione predefinita il browser gestisce l'HTML del server in modo molto efficiente. Suddivide l'analisi e il rendering dell'HTML in modo da evitare attività lunghe e ottimizzare la quantità di tempo totale del thread principale. Ciò comporta un tempo di blocco totale (TBT) inferiore, che è fortemente correlato all'INP.

Potresti fare affidamento su un framework frontend per creare il tuo sito web. In questo caso, assicurati di eseguire il rendering del componente HTML sul server. In questo modo, limiterai la quantità di rendering lato client iniziale richiesta dal tuo sito web e dovresti ottenere un'esperienza migliore.

  • Per React, ti consigliamo di utilizzare l'API DOM del server per eseguire il rendering dell'HTML sul server. Tuttavia, tieni presente che il metodo tradizionale di rendering lato server utilizza un approccio sincrono, che può comportare un tempo di risposta (TTFB) più lungo, nonché metriche successive come First Contentful Paint (FCP) e LCP. Se possibile, assicurati di utilizzare le API di streaming per Node.js o altri runtime JavaScript in modo che il server possa iniziare lo streaming di HTML nel browser il prima possibile. Next.js, un framework basato su React, fornisce molte best practice per impostazione predefinita. Oltre a eseguire il rendering automatico dell'HTML sul server, può anche generare codice HTML in modo statico per le pagine che non cambiano in base al contesto dell'utente (ad esempio l'autenticazione).
  • Anche Vue esegue il rendering lato client per impostazione predefinita. Tuttavia, come React, Vue può anche eseguire il rendering del codice HTML del componente sul server. Se possibile, sfrutta queste API lato server o valuta la possibilità di utilizzare un'astrazione di livello superiore per il tuo progetto Vue per semplificare l'implementazione delle best practice.
  • Per impostazione predefinita, Svelte esegue il rendering dell'HTML sul server. Tuttavia, se il codice del componente deve accedere a spazi dei nomi esclusivi del browser (ad esempio window), potresti non essere in grado di eseguire il rendering dell'HTML del componente sul server. Esplora approcci alternativi, ove possibile, in modo da non causare un rendering lato client non necessario. SvelteKit, che per Svelte è come Next.js per React, incorpora il maggior numero possibile di best practice nei progetti Svelte, in modo da evitare potenziali insidie nei progetti che utilizzano solo Svelte.

Limita la quantità di nodi DOM creati sul client

Quando i DOM sono di grandi dimensioni, l'elaborazione richiesta per il rendering tende ad aumentare. Indipendentemente dal fatto che il tuo sito web sia un'applicazione SPA completa o se inietta nuovi nodi in un DOM esistente a seguito di un'interazione per un'applicazione MPA, ti consigliamo di mantenere questi DOM il più piccoli possibile. In questo modo, potrai ridurre il lavoro necessario durante il rendering lato client per visualizzare il codice HTML, contribuendo a mantenere basso l'INP del tuo sito web.

Valuta un'architettura di worker per un servizio di streaming

Si tratta di una tecnica avanzata, che potrebbe non funzionare facilmente con ogni caso d'uso, ma che può trasformare il tuo MPA in un sito web che sembra caricarsi istantaneamente quando gli utenti passano da una pagina all'altra. Puoi utilizzare un service worker per eseguire la precache delle parti statiche del tuo sito web in CacheStorage, utilizzando al contempo l'API ReadableStream per recuperare il resto del codice HTML di una pagina dal server.

Se utilizzi questa tecnica correttamente, non crei HTML sul client, ma il caricamento istantaneo dei contenuti parziali dalla cache darà l'impressione che il tuo sito si carichi rapidamente. I siti web che utilizzano questo approccio possono sembrare quasi un'app SPA, ma senza i problemi del rendering lato client. Inoltre, riduci la quantità di codice HTML che richiedi al server.

In breve, l'architettura di un worker di un servizio di streaming non sostituisce la logica di navigazione integrata del browser, ma la integra. Per ulteriori informazioni su come ottenere questo risultato con Workbox, leggi l'articolo Applicazioni multipagina più veloci con gli stream.

Conclusione

Il modo in cui il tuo sito web riceve e esegue il rendering dell'HTML influisce sul rendimento. Se ti affidi al server per inviare tutto (o la maggior parte) del codice HTML necessario per il funzionamento del tuo sito web, ottieni molto senza costi: analisi e rendering incrementali e cessione automatica al thread principale per evitare attività lunghe.

Il rendering HTML lato client introduce una serie di potenziali problemi di prestazioni che in molti casi possono essere evitati. Tuttavia, a causa dei requisiti di ciascun sito web, non è possibile evitarlo completamente il 100% delle volte. Per ridurre le potenziali attività lunghe che possono derivare da un rendering eccessivo sul sito client, assicurati di inviare il maggior numero possibile di codice HTML del tuo sito web dal server, mantieni le dimensioni del DOM il più piccole possibile per l'HTML che deve essere visualizzato sul client e valuta architetture alternative per velocizzare l'invio di HTML al client, sfruttando al contempo l'analisi e il rendering incrementali forniti dal browser per l'HTML caricato dal server.

Se riesci a ridurre al minimo il rendering lato client del tuo sito web, migliorerai non solo l'INP del tuo sito web, ma anche altre metriche come LCP, TBT e, in alcuni casi, anche il TTFB.

Immagine hero di Unsplash, di Maik Jonietz.