Scopri come ottimizzare l'interazione del tuo sito web con Next Paint.
Interazione con Next Paint (INP) è una metrica Core Web Vital stabile che valuta l'adattabilità complessiva di una pagina alle interazioni degli utenti osservando la latenza di tutte le interazioni idonee che si verificano durante la durata della visita di un utente a una pagina. Il valore INP finale è l'interazione più lunga osservata (a volte ignorando i valori anomali).
Per offrire una buona esperienza utente, i siti web devono fare in modo che il valore di interazione con Next Paint sia pari o inferiore a 200 millisecondi. Per assicurarti di raggiungere questo target per la maggior parte degli utenti, una buona soglia da misurare è il 75° percentile di caricamenti pagine, segmentato tra dispositivi mobili e computer.
A seconda del sito web, potrebbero esserci poche interazioni o nessuna, ad esempio pagine contenenti prevalentemente testo e immagini con pochi o nessun elemento interattivo. Oppure, nel caso di siti web come editor di testo o giochi, potrebbero esserci centinaia o anche migliaia di interazioni. In entrambi i casi, quando il valore INP è elevato, l'esperienza utente è a rischio.
Migliorare INP richiede tempo e impegno, ma il premio è un'esperienza utente migliore. In questa guida, verrà esplorato un percorso per migliorare INP.
Scopri cosa causa un INP scarso
Per poter correggere le interazioni lente, devi avere dati che ti indicano se l'INP del tuo sito web è scarso o deve essere migliorato. Una volta raccolte queste informazioni, puoi entrare nel lab per iniziare a diagnosticare le interazioni lente e trovare una soluzione.
Rilevare interazioni lente sul campo
Idealmente, il tuo percorso verso l'ottimizzazione di INP inizia con i dati sul campo. Nella migliore delle ipotesi, i dati dei campi forniti da un fornitore di Real User Monitoring (RUM) forniranno non solo il valore INP di una pagina, ma anche dati contestuali che evidenziano quale interazione specifica è stata responsabile del valore INP stesso, se l'interazione si è verificata durante o dopo il caricamento della pagina, il tipo di interazione (clic, pressione di un tasto o tocco) e altre informazioni importanti.
Se non ti affidi a un fornitore RUM per ottenere dati dei campi, la guida ai dati sui campi INP ti consiglia di utilizzare il Report sull'esperienza utente di Chrome (CrUX) tramite PageSpeed Insights per colmare le lacune. CrUX è il set di dati ufficiale del programma Core Web Vitals e fornisce un riepilogo di alto livello delle metriche per milioni di siti web, incluso INP. Tuttavia, CrUX spesso non fornisce i dati contestuali che riceveresti da un provider RUM per aiutarti ad analizzare i problemi. Per questo motivo, consigliamo comunque ai siti di utilizzare un provider RUM, se possibile, oppure di implementare la propria soluzione RUM per integrare quanto disponibile in CrUX.
Diagnosi delle interazioni lente nel lab
Idealmente, ti consigliamo di iniziare a eseguire test nel lab una volta ottenuti i dati sul campo che suggeriscono interazioni lente. In assenza di dati sul campo, esistono alcune strategie per identificare le interazioni lente nel lab. Queste strategie includono seguire i flussi utente comuni e testare le interazioni lungo il percorso, nonché l'interazione con la pagina durante il caricamento (quando il thread principale è spesso il più intenso) per far emergere interazioni lente durante quella parte cruciale dell'esperienza utente.
Ottimizza le interazioni
Dopo aver identificato un'interazione lenta e poter riprodurla manualmente nel lab, il passaggio successivo consiste nell'ottimizzarla. Le interazioni possono essere suddivise in tre fasi:
- Il ritardo dell'input, che inizia quando l'utente avvia un'interazione con la pagina e termina quando l'evento richiama l'interazione.
- La durata dell'elaborazione, ovvero il tempo necessario per l'esecuzione dei callback di eventi fino al completamento.
- Il ritardo nella presentazione, ovvero il tempo impiegato dal browser per presentare il frame successivo contenente il risultato visivo dell'interazione.
La somma di queste tre fasi è la latenza totale dell'interazione. Ogni singola fase di un'interazione contribuisce alla latenza totale dell'interazione con una certa quantità di tempo. Di conseguenza, è importante sapere come ottimizzare ogni parte dell'interazione in modo che venga eseguita per il minor tempo possibile.
Identificare e ridurre il ritardo di input
Quando un utente interagisce con una pagina, la prima parte di questa interazione è il ritardo dell'input. A seconda di altre attività nella pagina, i ritardi nell'inserimento possono essere considerevoli. Ciò potrebbe essere dovuto a attività che si verificano sul thread principale (forse a causa del caricamento, dell'analisi e della compilazione degli script), della gestione del recupero, delle funzioni timer o anche di altre interazioni che si verificano in rapida successione e si sovrappongono.
Qualunque sia l'origine del ritardo di input di un'interazione, devi ridurre al minimo il ritardo di input, in modo che le interazioni possano iniziare a eseguire i callback di eventi il prima possibile.
Relazione tra valutazione dello script e attività lunghe durante l'avvio
Un aspetto fondamentale dell'interattività nel ciclo di vita della pagina è la fase di avvio. Quando una pagina si carica, inizialmente viene visualizzata, ma è importante ricordare che il semplice fatto che una pagina sia stata sottoposta a rendering non significa che il caricamento sia terminato. A seconda del numero di risorse necessarie a una pagina per diventare completamente funzionale, è possibile che gli utenti tenti di interagire con la pagina mentre è ancora in fase di caricamento.
Un elemento che può prolungare il ritardo di input di un'interazione durante il caricamento di una pagina è la valutazione dello script. Dopo che un file JavaScript è stato recuperato dalla rete, il browser deve ancora svolgere del lavoro prima che JavaScript possa essere eseguito; questo lavoro include l'analisi di uno script per garantire che la sua sintassi sia valida, la compilazione in bytecode e quindi l'esecuzione.
A seconda delle dimensioni di uno script, questo lavoro può introdurre lunghe attività nel thread principale, il che ritarda la risposta del browser ad altre interazioni dell'utente. Per fare in modo che la tua pagina sia reattiva all'input degli utenti durante il caricamento della pagina, è importante capire cosa puoi fare per ridurre la probabilità di attività lunghe durante il caricamento, in modo che la pagina sia sempre veloce.
Callback di eventi Optimize
Il ritardo di input è solo la prima parte di ciò che misura INP. Dovrai inoltre assicurarti che i callback eventi eseguiti in risposta a un'interazione utente possano essere completati il più rapidamente possibile.
Rimangono spesso al thread principale
Il miglior consiglio generale per ottimizzare i callback eventi è di svolgere il meno lavoro possibile. Tuttavia, la logica di interazione potrebbe essere complessa e potresti riuscire a ridurre solo marginalmente il lavoro svolto.
Se ritieni che questo sia il caso del tuo sito web, la cosa successiva che puoi provare a fare è suddividere il lavoro nei callback eventi in attività separate. In questo modo, il lavoro collettivo non diventa un'attività lunga che blocca il thread principale, il che consente di eseguire prima altre interazioni che altrimenti aspetterebbero sul thread principale.
setTimeout
è un modo per suddividere le attività, perché il callback passato viene eseguito in una nuova attività. Puoi utilizzare setTimeout
da solo o astrarre il suo utilizzo in una funzione separata per un rendimento più ergonomico.
Fornire una restituzione indiscriminata è meglio che non cedere del tutto, ma esiste un modo più articolato per cedere al thread principale, che prevede la restituzione subito dopo un callback di evento che aggiorna l'interfaccia utente in modo che la logica di rendering possa essere eseguita prima.
Rendita per consentire l'esecuzione più breve del lavoro di rendering
Una tecnica di rendimento più avanzata prevede la strutturazione del codice nei callback eventi per limitare ciò che viene eseguito solo alla logica necessaria per applicare gli aggiornamenti visivi al frame successivo. Tutto il resto può essere rimandato a un'attività successiva. Questo non solo mantiene i callback leggeri e agili, ma migliora anche il tempo di rendering per le interazioni, impedendo che gli aggiornamenti visivi blocchino il codice di callback dell'evento.
Immagina, ad esempio, un editor RTF che formatti il testo durante la digitazione, ma che aggiorni anche altri aspetti dell'interfaccia utente in risposta a ciò che hai scritto (come il conteggio delle parole, l'evidenziazione di errori di ortografia e altri importanti feedback visivi). Inoltre, l'applicazione potrebbe anche dover salvare ciò che hai scritto in modo che, se esci e poi torni, non hai perso il lavoro.
In questo esempio, le quattro cose che seguono devono verificarsi in risposta ai caratteri digitati dall'utente. Tuttavia, è necessario eseguire solo il primo elemento per visualizzare il frame successivo.
- Aggiorna la casella di testo con ciò che l'utente ha digitato e applica la formattazione richiesta.
- Aggiorna la parte dell'interfaccia utente che mostra il conteggio delle parole corrente.
- Esegui la logica per verificare la presenza di errori ortografici.
- Salva le modifiche più recenti (in locale o in un database remoto).
Il codice per eseguire questa operazione potrebbe essere simile al seguente:
textBox.addEventListener('input', (inputEvent) => {
// Update the UI immediately, so the changes the user made
// are visible as soon as the next frame is presented.
updateTextBox(inputEvent);
// Use `setTimeout` to defer all other work until at least the next
// frame by queuing a task in a `requestAnimationFrame()` callback.
requestAnimationFrame(() => {
setTimeout(() => {
const text = textBox.textContent;
updateWordCount(text);
checkSpelling(text);
saveChanges(text);
}, 0);
});
});
La visualizzazione seguente mostra come il rinvio di aggiornamenti non critici fino a dopo il frame successivo può ridurre la durata dell'elaborazione e, di conseguenza, la latenza dell'interazione complessiva.
![Una rappresentazione di un'interazione tramite tastiera e delle attività successive in due scenari. Nella figura in alto, l'attività di rendering critico e tutte le successive attività in background vengono eseguite in modo sincrono fino a quando non è arrivata l'opportunità di presentare un frame. Nella figura in basso, il lavoro critico per il rendering viene eseguito prima, poi cede al thread principale per presentare un nuovo frame prima. Le attività in background vengono eseguite successivamente.](https://web.dev/static/articles/optimize-inp/image/interaction-latency.png?authuser=6&hl=it)
Anche se l'uso di setTimeout()
all'interno di una chiamata requestAnimationFrame()
nell'esempio di codice precedente è certamente un po' esoterico, si tratta di un metodo efficace che funziona in tutti i browser per garantire che il codice non critico non blocchi il frame successivo.
Evita il layout thrashing
Il thrashing del layout, talvolta chiamato layout sincrono forzato, è un problema di prestazioni di rendering in cui il layout avviene in modo sincrono. Si verifica quando aggiorni gli stili in JavaScript e poi li leggi nella stessa attività. Esistono molte proprietà in JavaScript che possono causare il thrashing del layout.
![Una visualizzazione del thrashing del layout come mostrato nel riquadro delle prestazioni di Chrome DevTools.](https://web.dev/static/articles/optimize-inp/image/a-visualization-layout-t-cefcc10055727.png?authuser=6&hl=it)
Il thrashing del layout è un collo di bottiglia delle prestazioni perché, aggiornando gli stili e quindi richiedendo immediatamente i valori di questi stili in JavaScript, il browser è costretto a eseguire operazioni di layout sincrono che altrimenti avrebbe potuto aspettare di eseguire in modo asincrono in un secondo momento al termine dell'esecuzione dei callback di eventi.
Riduci al minimo il ritardo della presentazione
Il ritardo nella presentazione di un'interazione si riferisce al termine dell'esecuzione dei callback di eventi di un'interazione, fino al momento in cui il browser è in grado di visualizzare il frame successivo che mostra le modifiche visive risultanti.
Riduci al minimo le dimensioni del DOM
Quando il DOM di una pagina è ridotto, il lavoro di rendering di solito termina rapidamente. Tuttavia, quando i DOM diventano molto grandi, il lavoro di rendering tende a scalare all'aumentare delle dimensioni del DOM. La relazione tra il lavoro di rendering e le dimensioni del DOM non è lineare, ma i DOM di grandi dimensioni richiedono più lavoro rispetto ai DOM di dimensioni ridotte. Un DOM di grandi dimensioni costituisce un problema in due casi:
- Durante il rendering iniziale della pagina, quando un DOM di grandi dimensioni richiede molto lavoro per visualizzare lo stato iniziale della pagina.
- In risposta a un'interazione dell'utente, per cui un DOM di grandi dimensioni può causare un costo elevato degli aggiornamenti del rendering e, di conseguenza, aumentare il tempo necessario al browser per presentare il frame successivo.
Tieni presente che in alcuni casi non è possibile ridurre significativamente i DOM di grandi dimensioni. Anche se esistono degli approcci che puoi adottare per ridurre le dimensioni del DOM, come il appiattimento del DOM o l'aggiunta al DOM durante le interazioni degli utenti per mantenere ridotte le dimensioni del DOM iniziale, queste tecniche non possono che andare oltre.
Usa content-visibility
per eseguire il rendering di elementi fuori schermo in modo lento
Un modo per limitare il lavoro di rendering durante il caricamento della pagina e il lavoro di rendering in risposta alle interazioni degli utenti è affidarsi alla proprietà content-visibility
CSS, che di fatto equivale a eseguire il rendering degli elementi in modo lento quando si avvicinano all'area visibile. Anche se l'uso efficace di content-visibility
può richiedere un po' di pratica, vale la pena verificare se il risultato è un tempo di rendering inferiore che può migliorare l'INP della pagina.
Tieni presente i costi di rendimento quando esegui il rendering dell'HTML utilizzando JavaScript
In presenza di codice HTML, c'è l'analisi dell'HTML e, al termine dell'analisi dell'HTML in un DOM, il browser deve applicare stili, eseguire i calcoli del layout e, in seguito, eseguire il rendering del layout. Si tratta di un costo inevitabile, ma il modo con cui esegui il rendering dell'HTML è importante.
Quando il server invia HTML, arriva nel browser sotto forma di stream. Flussi di dati significa che la risposta HTML dal server arriva a blocchi. Il browser ottimizza il modo in cui gestisce un flusso mediante l'analisi incrementale dei blocchi di quel flusso man mano che arrivano e il rendering bit per bit. Si tratta di un'ottimizzazione delle prestazioni in quanto il browser genera implicitamente periodicamente e automaticamente durante il caricamento della pagina e ottieni questa operazione senza costi.
Sebbene la prima visita a un sito web richieda sempre una certa quantità di codice HTML, un approccio comune inizia con una quantità minima di codice HTML iniziale e successivamente viene utilizzato JavaScript per compilare l'area dei contenuti. I successivi aggiornamenti dell'area di contenuti avvengono anche in seguito alle interazioni degli utenti. In genere si parla di modello di applicazione a pagina singola (APS). Uno svantaggio di questo modello è che, eseguendo il rendering dell'HTML con JavaScript sul client, non solo ottieni il costo dell'elaborazione JavaScript per la creazione dell'HTML, ma anche il browser non produrrà finché non avrà terminato l'analisi e il rendering dell'HTML.
Tuttavia, è fondamentale ricordare che anche i siti web che non sono APS probabilmente comporteranno una certa quantità di rendering HTML tramite JavaScript a seguito delle interazioni. In genere questo è un problema, purché non esegui il rendering di grandi quantità di codice HTML sul client, il che può ritardare la presentazione del frame successivo. Tuttavia, è importante comprendere le implicazioni in termini di rendimento di questo approccio in relazione alla visualizzazione del codice HTML nel browser e come questo può influire sulla reattività del sito web all'input dell'utente se esegui il rendering di molto codice HTML tramite JavaScript.
Conclusione
Il miglioramento dell'INP del tuo sito è un processo iterativo. Quando correggi un'interazione lenta sul campo, è probabile che, soprattutto se il tuo sito web offre molta interattività, inizierai a individuare altre interazioni lente, oltre che tu dovrai ottimizzarle.
La chiave per migliorare l'INP è la persistenza. Con il tempo, puoi verificare la reattività della tua pagina rispetto a un punto in cui gli utenti sono soddisfatti dell'esperienza che stai offrendo loro. È anche probabile che, quando sviluppi nuove funzionalità per i tuoi utenti, potresti dover seguire la stessa procedura per ottimizzare le interazioni specifiche per loro. Richiederà tempo e fatica, ma è tempo e fatica ben spesi.
Immagine hero tratta da Unsplash, di David Pisnoy e modificata in conformità con la licenza di Unsplash.