Il rendering dell'HTML con JavaScript è diverso dal rendering dell'HTML inviato dal server e questo può influire sulle prestazioni. Scopri le differenze riportate in questa guida e cosa puoi fare per preservare le prestazioni di rendering del tuo sito web, in particolare per le interazioni.
L'analisi e il rendering del codice HTML sono attività che i browser fanno molto bene per impostazione predefinita per i siti web che utilizzano la logica di navigazione integrata nel browser, a volte denominati "caricamenti di pagine tradizionali" o "navigazioni difficili". Questi siti web a volte sono chiamati applicazioni multi-page (MPA).
Tuttavia, gli sviluppatori potrebbero aggirare le impostazioni predefinite del browser in base alle loro esigenze relative alle applicazioni. Questo vale sicuramente per i siti web che utilizzano il pattern applicazione a pagina singola (SPA), che crea dinamicamente grandi parti del codice HTML/DOM sul client con JavaScript. Il rendering lato client è il nome di questo pattern di progettazione e può avere effetti sull'Interaction to Next Paint (INP) del tuo sito web se il lavoro richiesto è eccessivo.
Questa guida ti aiuterà a comprendere la differenza tra l'utilizzo dell'HTML inviato dal server al browser e la sua creazione sul client con JavaScript e come quest'ultimo possa generare un'elevata latenza di interazione in momenti cruciali.
Modalità di rendering del codice HTML fornito dal server da parte del browser
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:
- Il browser invia una richiesta di navigazione per l'URL fornito.
- Il server risponde con il codice HTML in blocchi.
L'ultimo passaggio è fondamentale. È anche una delle ottimizzazioni più fondamentali delle prestazioni nella piattaforma di scambio server/browser ed è nota come streaming. Se il server è in grado di iniziare a inviare HTML il prima possibile e il browser non attende l'intera risposta, può elaborare l'HTML in blocchi man mano che arriva.
Come per la maggior parte delle cose che si verificano nel browser, l'analisi dell'HTML avviene all'interno delle attività. Quando il codice HTML viene trasmesso in streaming dal server al browser, quest'ultimo ottimizza l'analisi del codice HTML un po' alla volta, man mano che i bit del flusso arrivano in blocchi. Di conseguenza, il browser restituisce periodicamente il thread principale dopo l'elaborazione di ogni blocco, evitando attività lunghe. Ciò significa che durante l'analisi del codice HTML possono essere eseguite altre operazioni, incluso il lavoro di rendering incrementale necessario per presentare una pagina all'utente, nonché l'elaborazione delle interazioni dell'utente che potrebbero verificarsi durante il periodo di avvio cruciale della pagina. Questo approccio si traduce in un punteggio migliore di Interaction to Next Paint (INP) per la pagina.
Il consiglio? Quando esegui lo streaming di codice HTML dal server, ricevi l'analisi e il rendering incrementali e il rendimento automatico del codice HTML al thread principale senza costi. Con il rendering lato client non è questo il caso.
Modalità di rendering del codice HTML fornito da JavaScript da parte del browser
Sebbene ogni richiesta di navigazione verso una pagina richieda che il server fornisca una certa quantità di HTML, alcuni siti web utilizzano il pattern SPA. Questo approccio spesso comporta un payload iniziale minimo di HTML fornito dal server, ma in seguito il client completerà l'area dei contenuti principali di una pagina con codice HTML assemblato a partire dai dati recuperati dal server. Le navigazioni successive, a volte denominate in questo caso "navigazioni soft", vengono gestite interamente da JavaScript per completare la pagina con il nuovo codice HTML.
Il rendering lato client può avvenire anche in ambienti non APS in casi più limitati in cui il codice HTML viene aggiunto dinamicamente al DOM tramite JavaScript.
Esistono alcuni modi comuni per creare codice HTML o aggiungere al DOM tramite JavaScript:
- La proprietà
innerHTML
ti consente di impostare i contenuti di un elemento esistente tramite una stringa, che il browser analizza nel DOM. - Il metodo
document.createElement
consente di creare nuovi elementi da aggiungere al DOM senza utilizzare l'analisi HTML del browser. - Il metodo
document.write
ti consente di scrivere codice HTML nel documento (e il browser lo analizza, proprio come nell'approccio 1). Tuttavia, per una serie di motivi, sconsigliamo vivamente l'utilizzo didocument.write
.
Le conseguenze della creazione di HTML/DOM tramite JavaScript lato client possono essere significative:
- A differenza del codice HTML trasmesso 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 tua pagina può essere influenzato negativamente se stai creando troppo codice HTML/DOM alla volta sul client.
- Se l'HTML viene creato sul client durante l'avvio, le risorse a cui viene fatto riferimento al suo interno non verranno rilevate dallo scanner di precaricamento del browser. Questo avrà sicuramente un effetto negativo sulla Largest Contentful Paint (LCP) di una pagina. Anche se non si tratta di un problema di prestazioni di runtime, ma di un ritardo di rete nel recupero di risorse importanti, è consigliabile evitare che l'LCP del tuo sito web venga alterato eludendo questa fondamentale ottimizzazione delle prestazioni del browser.
Cosa puoi fare in merito all'impatto sulle prestazioni del rendering lato client
Se il tuo sito web dipende molto dal rendering lato client e hai notato valori INP scarsi nei dati dei campi, ti starai chiedendo se il rendering lato client ha qualcosa a che fare con il problema. Ad esempio, se il tuo sito web è un'APS, i dati dei campi potrebbero rivelare interazioni responsabili di un considerevole lavoro di rendering.
Qualunque sia la causa, ecco alcune potenziali cause che puoi esplorare per aiutarti a tornare in pista.
Fornisci quanto più HTML possibile dal server
Come accennato in precedenza, per impostazione predefinita il browser gestisce l'HTML dal server in modo molto efficiente. Suddivide l'analisi e il rendering del codice HTML in modo da evitare attività lunghe e ottimizza la quantità di tempo totale del thread principale. Ciò porta a una riduzione del Tempo di blocco totale (TBT), che è fortemente correlato all'INP.
È possibile che tu stia facendo affidamento su un framework di frontend per creare il tuo sito web. In tal caso, dovrai assicurarti di eseguire il rendering dell'HTML del componente sul server. Ciò limiterà la quantità di rendering iniziale lato client richiesta dal tuo sito web e dovrebbe portare a un'esperienza migliore.
- Per React, dovrai utilizzare l'API Server DOM per eseguire il rendering dell'HTML sul server. Tieni presente, però, che il metodo tradizionale di rendering lato server utilizza un approccio sincrono, che può portare a un Time to First Byte (TTFB) più lungo, oltre a 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 a trasmettere HTML al browser il prima possibile. Next.js, un framework basato su React, fornisce molte best practice per impostazione predefinita. Oltre a visualizzare automaticamente l'HTML sul server, può anche generare in modo statico il codice HTML per le pagine che non cambiano in base al contesto dell'utente (come l'autenticazione).
- Per impostazione predefinita, Vue esegue anche il rendering lato client. Tuttavia, come React, Vue può anche eseguire il rendering del codice HTML del componente sul server. Se possibile, sfrutta queste API lato server oppure prendi in considerazione un'astrazione di livello superiore per il tuo progetto Vue per semplificare l'implementazione delle best practice.
- Svelte visualizza il codice HTML sul server per impostazione predefinita, anche 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 di quel componente sul server. Esplora approcci alternativi dove possibile in modo da non causare rendering inutili lato client. SvelteKit, che corrisponde a Svelte come Next.js sta per React, incorpora molte best practice nei tuoi 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, il tempo di elaborazione necessario per eseguirne il rendering tende ad aumentare. Sia che il tuo sito web sia un'APS a tutti gli effetti o che stia inserendo nuovi nodi in un DOM esistente a seguito di un'interazione per una MPA, valuta la possibilità di mantenere i DOM il più ridotti possibile. Ciò contribuirà a ridurre il lavoro necessario durante il rendering lato client per visualizzare il codice HTML, possibilmente contribuendo a contenere l'INP del tuo sito web.
Considera l'architettura di un service worker di flussi di dati
Si tratta di una tecnica avanzata che potrebbe non funzionare facilmente in ogni caso d'uso, ma è in grado di trasformare l'MPA in un sito web che sembra caricarsi istantaneamente quando gli utenti passano da una pagina all'altra. Puoi utilizzare un service worker per prememorizzare nella cache le parti statiche del tuo sito web in CacheStorage
mentre utilizzi l'API ReadableStream
per recuperare il resto del codice HTML di una pagina dal server.
Se utilizzi correttamente questa tecnica, non crei HTML sul client, ma il caricamento istantaneo delle parti dei contenuti dalla cache darà l'impressione che il tuo sito si carichi rapidamente. I siti web che utilizzano questo approccio possono sembrare quasi come un'APS, ma senza i lati negativi del rendering lato client. Inoltre, riduce la quantità di codice HTML richiesta al server.
In breve, un'architettura del worker di un servizio di streaming non sostituisce la logica di navigazione integrata del browser, ma la aggiunge. Per ulteriori informazioni su come raggiungere questo obiettivo con Workbox, leggi Applicazioni multipagina più veloci con i flussi.
Conclusione
Il modo in cui il tuo sito web riceve e visualizza il codice HTML ha un impatto sulle prestazioni. Quando 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 passaggio automatico 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 ogni singolo sito web, non è sempre possibile evitarlo. Per ridurre le potenziali attività lunghe che possono derivare da un rendering eccessivo del sito client, assicurati di inviare dal server la maggior quantità di codice HTML del sito web, quando possibile, mantieni le dimensioni del DOM il più piccole possibili per l'HTML che deve essere visualizzato sul client e prendi in considerazione architetture alternative per velocizzare la distribuzione del codice 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 il più possibile 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.