Il rendering dell'HTML con JavaScript è diverso dal rendering dell'HTML inviato dal server e questo può influire sulle prestazioni. 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 del codice HTML sono operazioni che i browser hanno per impostazione predefinita in modo molto efficace per i siti web che utilizzano la logica di navigazione integrata del browser, talvolta chiamata "caricamenti di pagina tradizionali" o "navigazioni difficili". Questi siti web a volte sono chiamati applicazioni multipagina (MPA).
Tuttavia, gli sviluppatori potrebbero aggirare le impostazioni predefinite del browser per soddisfare le esigenze dell'applicazione. Questo è indubbiamente il caso dei siti web che utilizzano il pattern di applicazione a pagina singola (SPA, Single Page Application), che crea dinamicamente grandi parti di HTML/DOM sul client con JavaScript. Rendering lato client è il nome di questo pattern di progettazione e può influire sull'interazione con Next Paint (INP) del tuo sito web se il lavoro richiesto è eccessivo.
Questa guida ti aiuterà a valutare la differenza tra l'utilizzo del codice HTML inviato dal server al browser e la sua creazione sul client con JavaScript e come quest'ultimo può comportare 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 delle pagine tradizionali prevede la ricezione di codice 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 delle prestazioni più fondamentali nello scambio server/browser ed è nota come streaming. Se il server può iniziare a inviare codice HTML il prima possibile e il browser non attende il recapito dell'intera risposta, il browser potrà elaborare il codice HTML in blocchi man mano che arriva.
Come gran parte delle operazioni che avvengono nei browser, l'analisi del codice HTML avviene all'interno di altre attività. Quando l'HTML viene trasmesso in streaming dal server al browser, il browser ne ottimizza l'analisi un po' alla volta man mano che i bit del flusso arrivano in blocchi. La conseguenza è che il browser cede periodicamente al thread principale dopo l'elaborazione di ogni blocco, evitando attività lunghe. Ciò significa che durante l'analisi del codice HTML possono verificarsi altre operazioni, tra cui 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 migliore punteggio di Interaction to Next Paint (INP) per la pagina.
Il concetto? Quando trasmetti in streaming il codice HTML dal server, ricevi l'analisi e il rendering incrementali del codice HTML e il caricamento automatico e senza costi del thread principale. Questo non è possibile con il rendering lato client.
Modalità di rendering del codice HTML fornito da JavaScript nel browser
Mentre ogni richiesta di navigazione verso una pagina richiede una certa quantità di HTML che deve essere fornita dal server, alcuni siti web utilizzeranno il pattern SPA. Questo approccio spesso comporta un payload iniziale minimo di HTML fornito dal server, ma poi il client completerà l'area dei contenuti principali di una pagina con codice HTML assemblato dai dati recuperati dal server. navigazioni successive, chiamate a volte "navigazioni leggere" in questo caso, saranno gestiti interamente da JavaScript per compilare la pagina con nuovo codice HTML.
Il rendering lato client può verificarsi anche al di fuori delle SPA in casi più limitati in cui l'HTML viene aggiunto dinamicamente al DOM tramite JavaScript.
Esistono alcuni modi comuni per creare codice HTML o aggiungerlo al DOM tramite JavaScript:
- La proprietà
innerHTML
ti consente di impostare i contenuti su 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 n. 1). Tuttavia, a causa di una serie di motivi, l'utilizzo didocument.write
è fortemente sconsigliato.
Le conseguenze della creazione di HTML/DOM tramite JavaScript lato client possono essere significative:
- A differenza dell'HTML trasmesso in flusso 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 HTML/DOM contemporaneamente sul client.
- Se il codice 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. Ciò sicuramente influirà negativamente sulla visualizzazione elemento più grande (LCP) della pagina. Anche se non si tratta di un problema di prestazioni del runtime, bensì di un problema di ritardo di rete nel recupero di risorse importanti, è consigliabile evitare che l'LCP del tuo sito web venga influenzato dall'elusione di questa ottimizzazione di base delle prestazioni del browser.
Cosa puoi fare in merito all'impatto del rendering lato client sulle prestazioni
Se il tuo sito web dipende fortemente 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 sito web è un'APS, i dati sul campo possono indicare interazioni responsabili di un considerevole lavoro di rendering.
Qualunque sia la causa, ecco alcune potenziali cause che puoi esplorare per risolvere il problema.
Fornisci la maggiore quantità di codice HTML possibile dal server
Come già detto in precedenza, per impostazione predefinita il browser gestisce l'HTML dal server in modo molto efficiente. Interromperà l'analisi e il rendering del codice HTML in modo da evitare attività lunghe e ottimizzare la quantità di tempo totale del thread principale. Ciò determina un tempo di blocco totale (TBT) più basso e il valore da registrare è fortemente correlato all'INP.
Probabilmente ti servirai di un framework frontend per creare il tuo sito web. In questo caso, dovrai verificare di eseguire il rendering del codice HTML del componente sul server. Ciò limiterà la quantità di rendering iniziale lato client che il tuo sito web richiederà e dovrebbe portare a un'esperienza migliore.
- Per React, utilizzerai l'API Server DOM 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 aumento del tempo di esecuzione del Time to First Byte (TTFB) e metriche successive come First Contentful Paint (FCP) e LCP. Se possibile, assicurati di utilizzare le API di inserimento flussi per Node.js o altri runtime JavaScript in modo che il server possa iniziare a trasmettere codice HTML al browser il prima possibile. Next.js, un framework basato sulle reazioni, offre molte best practice per impostazione predefinita. Oltre a eseguire il rendering automatico del codice HTML sul server, può generare codice HTML in modo statico 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 tuo componente sul server. Sfrutta queste API lato server ove possibile o prendi in considerazione un'astrazione di livello superiore per il tuo progetto Vue per semplificare l'implementazione delle best practice.
- Svelte esegue il rendering del codice HTML sul server per impostazione predefinita, ma se il codice del tuo componente richiede l'accesso a spazi dei nomi esclusivi del browser (ad esempio
window
), potresti non essere in grado di visualizzare il codice HTML di quel componente sul server. Cerca di adottare approcci alternativi, se possibile, in modo da non causare un rendering non necessario sul lato client. SvelteKit, che equivale a Svelte come Next.js è a 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, l'elaborazione necessaria per eseguirne il rendering tende ad aumentare. Sia che il tuo sito web sia un SPA completo o che inserisca nuovi nodi in un DOM esistente a seguito di un'interazione per un MPA, valuta la possibilità di mantenere questi DOM il più possibile ridotti. In questo modo, sarà possibile ridurre il lavoro necessario durante il rendering lato client per visualizzare questo codice HTML, contribuendo probabilmente a ridurre il valore INP del sito web.
Valuta un'architettura di worker di servizi di streaming
Si tratta di una tecnica avanzata che potrebbe non funzionare facilmente con tutti i casi d'uso, ma è in grado di trasformare l'MPA in un sito web che sembra caricarsi all'istante 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 questa tecnica correttamente, non crei HTML sul client, ma il caricamento istantaneo di parti dei contenuti dalla cache darà l'impressione che il tuo sito venga caricato rapidamente. I siti web che utilizzano questo approccio possono sembrare quasi un'APS, ma senza gli svantaggi del rendering lato client. Inoltre, riduce la quantità di HTML che richiedi al server.
In breve, un'architettura di worker di un servizio di streaming non sostituisce la logica di navigazione integrata del browser, ma la si aggiunge. Per ulteriori informazioni su come ottenere questo risultato con Workbox, leggi Applicazioni multipagina più veloci con gli stream.
Conclusione
Il modo in cui il tuo sito web riceve e esegue il rendering del codice HTML influisce sul rendimento. Quando ti affidi al server per inviare tutto (o la maggior parte) del codice HTML necessario per il funzionamento del tuo sito web, ricevi 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 rendimento che possono essere evitati in molti casi. Tuttavia, a causa dei requisiti di ogni singolo sito web, questo non può essere evitato del tutto. Per ridurre le potenziali attività lunghe che possono essere causate da un rendering eccessivo del sito client, assicurati di inviare dal server la maggiore quantità di codice HTML del tuo sito web, quando possibile, mantieni le dimensioni DOM più ridotte possibili per l'HTML che deve essere sottoposto a rendering 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 al minimo il rendering lato client del tuo sito web, non solo migliorerai l'INP del sito web, ma anche altre metriche come LCP, TBT e, in alcuni casi, persino il tuo TTFB.
Immagine hero da Unsplash, di Maik Jonietz.