Ottimizza l'interazione con la prossima visualizzazione

Scopri come ottimizzare l'interazione del tuo sito web con Next Paint.

Interaction to Next Paint (INP) è una metrica di Segnali web essenziali stabili 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 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 dovrebbero cercare di avere un'interazione con Next Paint di 200 millisecondi o meno. Per assicurarti di raggiungere questo target per la maggior parte degli utenti, una buona soglia da misurare è il 75° percentile di caricamenti pagine, segmentato su dispositivi mobili e computer.

I valori INP validi sono pari o inferiori a 200 millisecondi, i valori scarsi sono superiori a 500 millisecondi e qualsiasi elemento intermedio deve essere migliorato.

A seconda del sito web, potrebbero esserci poche interazioni o nessuna, ad esempio pagine con prevalentemente testo e immagini con un numero minimo o nullo di elementi interattivi. Oppure, nel caso di siti web come editor di testo o giochi, le interazioni potrebbero essere centinaia, addirittura migliaia. In entrambi i casi, con un INP elevato, l'esperienza utente è a rischio.

Il miglioramento INP richiede tempo e impegno, ma il premio è un'esperienza utente migliore. In questa guida verrà esplorato un percorso per migliorare l'INP.

Scopri la causa di una scarsa INP

Prima di poter correggere le interazioni lente, avrai bisogno di dati per indicare se l'INP del tuo sito web è scarso o deve essere migliorato. Una volta raccolte le informazioni, puoi accedere al lab per iniziare a diagnosticare le interazioni lente e trovare una soluzione.

Trovare interazioni lente sul campo

Idealmente, il tuo percorso per l'ottimizzazione dell'INP inizierà con i dati sul campo. Nella migliore delle ipotesi, i dati dei campi di un provider di monitoraggio degli utenti reali (RUM) ti 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 pagina, il tipo di interazione (clic, pressione tasti o tocco) e altre informazioni importanti.

Se non ti affidi a un fornitore RUM per ottenere dati sul campo, la guida ai dati sul campo INP consiglia di usare 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 relative a milioni di siti web, incluso INP. Tuttavia, CrUX spesso non fornisce i dati contestuali che riceveresti da un fornitore di RUM per aiutarti ad analizzare i problemi. Per questo motivo, consigliamo comunque ai siti di utilizzare un provider RUM quando possibile o di implementare la propria soluzione RUM per integrare ciò che è disponibile in CrUX.

Diagnosi delle interazioni lente nel lab

Idealmente, dovresti iniziare i test in laboratorio una volta che hai 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 il monitoraggio dei flussi utente comuni e la verifica delle interazioni lungo il percorso, nonché l'interazione con la pagina durante il caricamento, ovvero quando il thread principale è spesso più intenso, per far emergere interazioni lente durante quella parte cruciale dell'esperienza utente.

Ottimizza le interazioni

Dopo che hai identificato un'interazione lenta e puoi riprodurla manualmente nel lab, il passaggio successivo consiste nell'ottimizzarla. Le interazioni possono essere suddivise in tre fasi:

  1. Il ritardo input, che inizia quando l'utente avvia un'interazione con la pagina e termina quando inizia l'esecuzione dei callback dell'evento per l'interazione.
  2. La durata dell'elaborazione, ovvero il tempo necessario per l'esecuzione fino al completamento dei callback degli eventi.
  3. Il ritardo di 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 a una certa quantità di tempo alla latenza totale dell'interazione, quindi è 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 quell'interazione è il ritardo di input. A seconda di altre attività sulla pagina, i ritardi nell'inserimento possono essere molto lunghi. Ciò potrebbe essere dovuto ad attività che si verificano nel thread principale (ad esempio a causa del caricamento, dell'analisi e della compilazione degli script), della gestione del recupero, delle funzioni timer o persino di altre interazioni che si verificano in rapida successione e che si sovrappongono tra loro.

Qualunque sia l'origine del ritardo di input di un'interazione, conviene ridurre al minimo il ritardo di input affinché le interazioni possano iniziare a eseguire callback di eventi il prima possibile.

Relazione tra la valutazione degli script e attività lunghe durante l'avvio

Un aspetto fondamentale dell'interattività nel ciclo di vita di una pagina è durante l'avvio. La pagina viene visualizzata all'inizio quando viene caricata, ma è importante ricordare che il semplice fatto che una pagina sia stata renderizzata non significa che il caricamento della pagina è terminato. A seconda del numero di risorse necessarie a una pagina per raggiungere la sua piena funzionalità, è possibile che gli utenti tentino di interagire con la pagina mentre è ancora in fase di caricamento.

Un aspetto che può estendere il ritardo di input di un'interazione durante il caricamento di una pagina è la valutazione degli script. Dopo che un file JavaScript è stato recuperato dalla rete, il browser ha ancora del lavoro da fare prima che JavaScript possa essere eseguito; tale lavoro include l'analisi di uno script per garantire la validità della sintassi, la compilazione in bytecode e, infine, l'esecuzione.

A seconda delle dimensioni di uno script, questa operazione può introdurre attività lunghe nel thread principale, che ritardano la risposta del browser ad altre interazioni degli utenti. Per fare in modo che la pagina rimanga adattabile all'input dell'utente durante il caricamento, è importante capire cosa puoi fare per ridurre la probabilità di svolgere attività lunghe durante questo processo, in modo che la pagina rimanga concisa.

Ottimizza le richiamate degli eventi

Il ritardo di input è solo la prima parte di ciò che INP misura. Devi inoltre assicurarti che i callback degli eventi eseguiti in risposta a un'interazione dell'utente vengano completati il più rapidamente possibile.

Restituisci spesso al thread principale

Il miglior consiglio generale per ottimizzare le richiamate degli eventi è evitare il minimo lavoro possibile. Tuttavia, la logica di interazione potrebbe essere complessa e potresti essere in grado di ridurre solo marginalmente il lavoro svolto.

Se scopri che questo è il caso del tuo sito web, la prossima cosa che puoi provare è suddividere il lavoro nei callback degli 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 sarebbero in attesa nel thread principale.

setTimeout è un modo per suddividere le attività, perché il callback passato all'attività viene eseguito in una nuova attività. Puoi utilizzare setTimeout da solo o astrarre l'utilizzo in una funzione separata per una resa più ergonomica.

È meglio cedere indiscriminatamente che non cedere affatto; tuttavia, c'è un modo più articolato di cedere al thread principale, e questo comporta solo l'esecuzione immediata dopo un callback di un evento che aggiorna l'interfaccia utente, in modo che la logica di rendering possa essere eseguita prima.

Resa per consentire il lavoro di rendering più breve

Una tecnica di resa più avanzata prevede la strutturazione del codice nei callback degli eventi per limitare ciò che viene eseguito solo alla logica necessaria per applicare aggiornamenti visivi per il frame successivo. Tutto il resto può essere differito a un'attività successiva. In questo modo i callback non solo sono leggeri e agili, ma migliora anche il tempo di rendering per le interazioni, non consentendo il blocco degli aggiornamenti visivi in base al codice di callback dell'evento.

Ad esempio, immagina un editor RTF che formatta il testo mentre digiti, ma al contempo aggiorni anche altri aspetti dell'interfaccia utente in risposta a ciò che hai scritto (come conteggio delle parole, evidenziando errori ortografici e altri importanti feedback visivi). Inoltre, l'applicazione potrebbe anche dover salvare ciò che hai scritto in modo da non perdere nessun lavoro, se esci e poi torni.

In questo esempio, le quattro cose seguenti devono verificarsi in risposta ai caratteri digitati dall'utente. Tuttavia, solo il primo elemento deve essere completato prima di presentare il frame successivo.

  1. Aggiorna la casella di testo con ciò che l'utente ha digitato e applica la formattazione richiesta.
  2. Aggiorna la parte dell'interfaccia utente che mostra il conteggio delle parole corrente.
  3. Esegui la logica per verificare l'eventuale presenza di errori ortografici.
  4. Salva le modifiche più recenti (in locale o in un database remoto).

Il codice per eseguire questa operazione potrebbe avere il seguente aspetto:

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 al frame successivo possa ridurre la durata dell'elaborazione e, di conseguenza, la latenza complessiva dell'interazione.

Illustrazione di un'interazione con la tastiera e attività successive in due scenari. Nella figura in alto, l'attività critica per il rendering e tutte le attività successive in background vengono eseguite in modo sincrono fino all'opportunità di presentare un frame. Nella figura in basso, le operazioni critiche per il rendering vengono eseguite prima e quindi passate al thread principale per presentare prima un nuovo frame. Le attività in background vengono eseguite successivamente.
Fai clic sulla figura sopra per visualizzare una versione ad alta risoluzione.

Sebbene l'uso di setTimeout() all'interno di una chiamata requestAnimationFrame() nell'esempio di codice precedente sia puramente un po' esoterico, è un metodo efficace che funziona in tutti i browser per garantire che il codice non critico non blocchi il frame successivo.

Evita il thrashing del layout

Il thrash di layout, a volte chiamato layout sincrono forzato, è un problema di prestazioni del 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 la thrash del layout.

Una visualizzazione del thrash di layout come mostrato nel riquadro delle prestazioni di Chrome DevTools.
Un esempio di thrash del layout, come mostrato nel riquadro delle prestazioni di Chrome DevTools. Le attività di rendering che prevedono l'eliminazione del layout verranno contrassegnate da un triangolo rosso nell'angolo in alto a destra della parte dello stack di chiamate, spesso etichettato come Ricalcola stile o Layout.

Il thrashing del layout è un collo di bottiglia delle prestazioni perché, aggiornando gli stili e quindi richiedendo immediatamente i relativi valori in JavaScript, il browser è costretto a svolgere un lavoro di layout sincrono che altrimenti avrebbe potuto attendere l'esecuzione asincrona in un secondo momento, una volta terminata l'esecuzione dei callback degli eventi.

Riduci al minimo il ritardo della presentazione

Il ritardo di presentazione degli indicatori di interazione va dal momento in cui i callback degli eventi di un'interazione sono stati completati, fino al momento in cui il browser è in grado di colorare il frame successivo che mostra le modifiche visive risultanti.

Riduci al minimo le dimensioni del DOM

Quando il DOM di una pagina è di dimensioni ridotte, il lavoro di rendering in genere termina rapidamente. Tuttavia, quando i DOM diventano molto grandi, il lavoro di rendering tende a scalare all'aumentare delle dimensioni dei DOM. La relazione tra il lavoro di rendering e le dimensioni del DOM non è lineare, ma i DOM di grandi dimensioni richiedono più lavoro per il rendering rispetto ai DOM di piccole dimensioni. Un DOM di grandi dimensioni presenta problemi in due casi:

  1. Durante il rendering iniziale della pagina, dove un DOM di grandi dimensioni richiede molto lavoro per visualizzare lo stato iniziale della pagina.
  2. In risposta a un'interazione dell'utente, per cui un DOM di grandi dimensioni può causare costi molto costosi 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 in modo significativo i DOM di grandi dimensioni. Anche se ci sono approcci che puoi adottare per ridurre le dimensioni del DOM, come appiattire il DOM o aggiungerlo al DOM durante le interazioni degli utenti per mantenere ridotte le dimensioni iniziali del DOM, queste tecniche possono andare oltre.

Usa content-visibility per eseguire il rendering lento degli elementi fuori schermo

Un modo per limitare il numero di operazioni di rendering durante il caricamento della pagina e di rendering in risposta alle interazioni degli utenti è affidarti alla proprietà content-visibility CSS, il che equivale a eseguire il rendering lento degli elementi quando si avvicinano all'area visibile. Anche se content-visibility può richiedere una certa pratica per un utilizzo efficace, vale la pena verificare se il risultato è un tempo di rendering inferiore che può migliorare l'INP della tua pagina.

Tieni presente i costi legati alle prestazioni durante il rendering del codice HTML utilizzando JavaScript.

Se è presente codice HTML, è in corso l'analisi HTML e, dopo che il browser ha terminato l'analisi dell'HTML in un DOM, deve applicare stili, eseguire calcoli relativi al layout e, in seguito, eseguire il rendering del layout. Questo è un costo inevitabile, ma come procedi nel rendering dell'HTML è importante.

Quando il server invia il codice HTML, questo viene visualizzato nel browser sotto forma di stream. Flusso indica che la risposta HTML dal server arriva in blocchi. Il browser ottimizza la gestione di un flusso analizzando in modo incrementale i blocchi di quel flusso man mano che arrivano e visualizzandoli bit per bit. Si tratta di un'ottimizzazione delle prestazioni in quanto il browser genera implicitamente periodicamente e automaticamente durante il caricamento pagina e il risultato è senza costi.

Anche se la prima visita a un sito web implicherà sempre una certa quantità di codice HTML, un approccio comune inizia con una porzione iniziale minima di HTML e successivamente viene utilizzato JavaScript per completare l'area dei contenuti. Anche i successivi aggiornamenti a questa area di contenuti avvengono in seguito alle interazioni degli utenti. In genere, questo è il modello di applicazione a pagina singola (SPA). Uno svantaggio di questo pattern è che, eseguendo il rendering dell'HTML con JavaScript sul client, non solo ti viene addebitato il costo dell'elaborazione JavaScript per la creazione dell'HTML, ma anche il browser non genera risultati fino a quando non ha completato l'analisi del codice HTML e non ne ha eseguito il rendering.

Tuttavia, è fondamentale ricordare che anche i siti web che non sono APS comportano probabilmente una certa quantità di rendering HTML tramite JavaScript a seguito delle interazioni. Questo non è un problema, purché tu non stia eseguendo il rendering di grandi quantità di HTML sul client, il che potrebbe ritardare la presentazione del frame successivo. Tuttavia, è importante comprendere le implicazioni di questo approccio relativamente alle prestazioni del rendering del codice HTML nel browser e come questo può influenzare la reattività del sito web in base all'input dell'utente se si esegue il rendering di una grande quantità di codice HTML tramite JavaScript.

Conclusione

Il miglioramento dell'INP del tuo sito è un processo iterativo. Quando correggi un'interazione lenta sul campo, è probabile che, specialmente se il tuo sito web offre molta interattività, inizi a trovare altre interazioni lente e che anche tu debba ottimizzarle.

La chiave per migliorare l'INP è la persistenza. Con il tempo, potrai impostare la reattività della tua pagina in un punto in cui gli utenti sono soddisfatti dell'esperienza che offri. È probabile inoltre che, quando sviluppi nuove funzionalità per i tuoi utenti, tu debba eseguire lo stesso processo per ottimizzare le loro interazioni specifiche. Ci vogliono tempo e impegno, ma sono tempi e sforzi ben spesi.

Immagine hero di Unsplash, realizzata da David Pisnoy e modificata in conformità con la licenza Unsplash.