Trova interazioni lente sul campo

Scopri come individuare le interazioni lente nei dati dei campi del tuo sito web in modo da trovare opportunità per migliorarne l'interazione con Next Paint.

I dati reali sono dati che indicano in che modo gli utenti effettivi utilizzano il tuo sito web. Anticipa i problemi che non è possibile trovare solo nei dati del lab. Per quanto riguarda il report Interaction to Next Paint (INP), i dati sul campo sono essenziali per identificare le interazioni lente e forniscono indizi vitali per aiutarti a risolverli.

In questa guida scoprirai come valutare rapidamente l'INP del tuo sito web utilizzando i dati dei campi del Report sull'esperienza utente di Chrome (CrUX) per capire se il tuo sito web presenta problemi con l'INP. In seguito, imparerai a utilizzare la build di attribuzione della libreria JavaScript degli elementi web di vita, e le nuove informazioni ricavate dall'API Long Animation Frames (LoAF), per raccogliere e interpretare i dati dei campi per le interazioni lente sul tuo sito web.

Iniziare con CrUX per valutare l'INP del tuo sito web

Se non raccogli dati reali dagli utenti del tuo sito web, CrUX può essere un buon punto di partenza. CrUX raccoglie dati sul campo da utenti reali di Chrome che hanno attivato l'invio di dati telemetrici.

I dati di CrUX vengono visualizzati in una serie di aree diverse e dipendono dall'ambito delle informazioni che stai cercando. CrUX può fornire dati relativi a INP e ad altri Segnali web essenziali per:

  • Singole pagine e intere origini che utilizzano PageSpeed Insights.
  • Tipi di pagine. Ad esempio, molti siti web di e-commerce hanno i tipi Pagina dei dettagli del prodotto e Pagina della scheda di prodotto. Puoi ottenere dati CrUX per tipi di pagina univoci in Search Console.

Come punto di partenza, puoi inserire l'URL del tuo sito web in PageSpeed Insights. Una volta inserito l'URL, i relativi dati dei campi, se disponibili, verranno visualizzati per più metriche, incluso l'INP. Puoi utilizzare i pulsanti di attivazione/disattivazione anche per controllare i valori INP per le dimensioni per dispositivi mobili e desktop.

Dati dei campi mostrati da CrUX in PageSpeed Insights, che mostrano LCP, INP, CLS ai tre Segnali web essenziali e TTFB, FCP come metriche diagnostiche e FID come metrica Segnali web essenziali deprecata.
Una lettura dei dati CrUX come mostrato in PageSpeed Insights. In questo esempio, l'INP della pagina web specifica deve essere migliorato.

Questi dati sono utili perché indicano se c'è un problema. Tuttavia, CrUX non è in grado di indicarti cosa causa i problemi. Sono disponibili molte soluzioni per il monitoraggio degli utenti reali (RUM, Real User Monitoring) che ti aiuteranno a raccogliere i dati dei campi dagli utenti del tuo sito web per rispondere a questa domanda; un'opzione è raccogliere personalmente i dati dei campi utilizzando la libreria JavaScript dei file web vitals.

Raccogli i dati dei campi con la libreria JavaScript web-vitals

La libreria JavaScript web-vitals è uno script che puoi caricare sul tuo sito web per raccogliere i dati dei campi dagli utenti del sito. Puoi utilizzarla per registrare una serie di metriche, tra cui l'INP nei browser che la supportano.

Supporto dei browser

  • 96
  • 96
  • x
  • x

Origine

La build standard della libreria degli elementi vitali web può essere utilizzata per ottenere i dati INP di base dagli utenti sul campo:

import {onINP} from 'web-vitals';

onINP(({name, value, rating}) => {
  console.log(name);    // 'INP'
  console.log(value);   // 512
  console.log(rating);  // 'poor'
});

Per analizzare i dati dei campi provenienti dagli utenti, devi inviarli da qualche parte:

import {onINP} from 'web-vitals';

onINP(({name, value, rating}) => {
  // Prepare JSON to be sent for collection. Note that
  // you can add anything else you'd want to collect here:
  const body = JSON.stringify({name, value, rating});

  // Use `sendBeacon` to send data to an analytics endpoint.
  // For Google Analytics, see https://github.com/GoogleChrome/web-vitals#send-the-results-to-google-analytics.
  navigator.sendBeacon('/analytics', body);
});

Tuttavia, questi dati da soli non ti diranno molto di più di CrUX. È qui che entra in gioco la raccolta di attribuzione della libreria di elementi vitali per il web.

Fai ancora di più con la creazione di attribuzione della libreria di vitali web

La build dell'attribuzione della libreria degli elementi vitali web mostra dati aggiuntivi che puoi ottenere dagli utenti sul campo per aiutarti a risolvere meglio i problemi delle interazioni problematiche che influiscono sull'INP del tuo sito web. Questi dati sono accessibili tramite l'oggetto attribution visualizzato nel metodo onINP() della libreria:

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, rating, attribution}) => {
  console.log(name);         // 'INP'
  console.log(value);        // 512
  console.log(rating);       // 'poor'
  console.dir(attribution);  // Attribution data
});
Come vengono visualizzati i log della console dalla libreria degli eventi web. In questo esempio, la console mostra il nome della metrica (INP), il valore INP (56), che si trova all'interno delle soglie INP (buono) e i vari bit di informazioni mostrati nell'oggetto Attribution, incluse le voci dell'API The Long Animation Frame.
Come vengono visualizzati nella console i dati della libreria degli elementi vitali web.

Oltre all'INP della pagina, la generazione dell'attribuzione fornisce molti dati che puoi utilizzare per aiutarti a comprendere i motivi delle interazioni lente, inclusa la parte dell'interazione su cui dovresti concentrarti. Può aiutarti a rispondere a domande importanti quali:

  • "L'utente ha interagito con la pagina durante il caricamento?"
  • "I gestori di eventi dell'interazione sono stati eseguiti per molto tempo?"
  • "L'avvio del codice del gestore di eventi di interazione è stato ritardato? Se sì, che cos'altro stava accadendo nel thread principale in quel momento?"
  • "L'interazione ha causato molto lavoro di rendering che ha ritardato la visualizzazione del frame successivo?"

La seguente tabella mostra alcuni dei dati di attribuzione di base che puoi ottenere dalla libreria e che possono aiutarti a comprendere alcune cause generali delle interazioni lente sul tuo sito web:

attribution chiave dell'oggetto Dati
interactionTarget Un selettore CSS che punta all'elemento che ha generato il valore INP della pagina, ad esempio button#save.
interactionType Il tipo di interazione, generata da clic, tocchi o input da tastiera.
inputDelay* Il ritardo di input dell'interazione.
processingDuration* Il tempo che intercorre tra l'esecuzione del primo listener di eventi in risposta all'interazione dell'utente e il completamento dell'elaborazione di tutti i listener di eventi.
presentationDelay* Il ritardo di presentazione dell'interazione, che si verifica dal momento in cui terminano i gestori di eventi al momento in cui viene visualizzato il frame successivo.
longAnimationFrameEntries* Voci dalla LoAF associate all'interazione. Vedi la prossima per ulteriori informazioni.
*Novità della versione 4

A partire dalla versione 4 della libreria degli elementi vitali web, puoi ottenere informazioni ancora più approfondite sulle interazioni problematiche attraverso i dati forniti con le suddivisioni della fase INP (ritardo dell'input, durata dell'elaborazione e ritardo della presentazione) e l'API LoAF (Long Animation Frame).

API Long Animation Frame (LoAF)

Supporto dei browser

  • 123
  • 123
  • x
  • x

Origine

Il debug delle interazioni mediante dati sul campo è un'attività complessa. Con i dati di LoAF, tuttavia, è ora possibile ottenere informazioni migliori sulle cause alla base delle interazioni lente, poiché LoAF espone una serie di tempistiche dettagliate e altri dati che è possibile utilizzare per individuare le cause precise e, soprattutto, dove l'origine del problema è nel codice del tuo sito web.

La build di attribuzione della libreria degli elementi vitali web espone un array di voci LoAF sotto la chiave longAnimationFrameEntries dell'oggetto attribution. Nella tabella seguente sono elencati alcuni bit chiave di dati che puoi trovare in ogni voce LoAF:

Chiave oggetto voce LoAF Dati
duration La durata del frame dell'animazione lungo, fino al termine del layout, ma senza pittura e compositing.
blockingDuration La quantità totale di tempo nel frame in cui il browser non è stato in grado di rispondere rapidamente a causa di attività lunghe. Questo tempo di blocco può includere attività lunghe che eseguono JavaScript, nonché qualsiasi attività di rendering lunga successiva nel frame.
firstUIEventTimestamp Il timestamp del momento in cui l'evento è stato messo in coda durante il frame. Utile per capire l'inizio del ritardo di input di un'interazione.
startTime Il timestamp iniziale del frame.
renderStart L'inizio del rendering del frame. Ciò include qualsiasi callback di requestAnimationFrame (e callback ResizeObserver se applicabile), ma potenzialmente prima dell'inizio di qualsiasi operazione di stile/layout.
styleAndLayoutStart Quando lo stile/il layout si applica nel frame. Può essere utile per capire la lunghezza del lavoro di stile/layout quando si interpretano altri timestamp disponibili.
scripts Un array di elementi contenenti informazioni di attribuzione dello script che contribuiscono all'INP della pagina.
Una visualizzazione di un lungo frame di animazione secondo il modello LoAF.
Un diagramma dei tempi di un lungo frame di animazione in base all'API LoAF (meno blockingDuration).

Tutte queste informazioni possono fornirti molte informazioni su ciò che rallenta un'interazione, ma l'array scripts a cui vengono visualizzate le voci LoAF dovrebbe essere di particolare interesse:

Chiave oggetto attribuzione script Dati
invoker L'invocatore. Può variare in base al tipo di callback descritto nella riga successiva. Esempi di richiamatori possono essere valori come 'IMG#id.onload', 'Window.requestAnimationFrame' o 'Response.json.then'.
invokerType Il tipo di callback. Può essere 'user-callback', 'event-listener', 'resolve-promise', 'reject-promise', 'classic-script' o 'module-script'.
sourceURL L'URL dello script da cui ha avuto origine il frame dell'animazione lungo.
sourceCharPosition La posizione del carattere nello script identificato da sourceURL.
sourceFunctionName Il nome della funzione nello script identificato.

Ogni voce in questo array contiene i dati mostrati in questa tabella, che offrono informazioni sullo script responsabile dell'interazione lenta e sulla relativa responsabilità.

Misura e identifica le cause comuni alla base delle interazioni lente

Per darti un'idea di come potresti utilizzare queste informazioni, questa guida ora spiegherà come utilizzare i dati LoAF presenti nella libreria web-vitals per determinare alcune cause delle interazioni lente.

Lunghe durate di elaborazione

La durata dell'elaborazione di un'interazione è il tempo necessario per l'esecuzione fino al completamento dei callback del gestore di eventi registrato dell'interazione e di qualsiasi altro evento intermedio. Le durate di elaborazione elevate vengono indicate nella libreria degli elementi vitali web:

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {processingDuration} = attribution; // 512.5
});

È naturale pensare che la causa principale di un'interazione lenta è che l'esecuzione del codice del gestore di eventi ha richiesto troppo tempo, ma non sempre. Una volta verificato che è questo il problema, puoi analizzare più a fondo i dati relativi al LoAF:

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {processingDuration} = attribution; // 512.5

  // Get the longest script from LoAF covering `processingDuration`:
  const loaf = attribution.longAnimationFrameEntries.at(-1);
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  if (script) {
    // Get attribution for the long-running event handler:
    const {invokerType} = script;        // 'event-listener'
    const {invoker} = script;            // 'BUTTON#update.onclick'
    const {sourceURL} = script;          // 'https://example.com/app.js'
    const {sourceCharPosition} = script; // 83
    const {sourceFunctionName} = script; // 'update'
  }
});

Come puoi vedere nello snippet di codice precedente, puoi lavorare con i dati LoAF per individuare la causa precisa che ha portato a un'interazione con valori di durata di elaborazione elevata, tra cui:

  • L'elemento e il relativo listener di eventi registrato.
  • Il file di script e la posizione del carattere al suo interno contenente il codice del gestore di eventi a lunga esecuzione.
  • Il nome della funzione.

Questo tipo di dati ha un valore inestimabile. Non dovrai più fare il lavoro necessario per scoprire esattamente quale interazione, o quali dei suoi gestori di eventi, sono stati responsabili dei valori elevati di durata dell'elaborazione. Inoltre, poiché spesso gli script di terze parti possono registrare i propri gestori di eventi, puoi determinare se la responsabilità è dovuta o meno al tuo codice. Per il codice su cui hai il controllo, dovrai prendere in considerazione l'ottimizzazione delle attività lunghe.

Ritardi di input lunghi

Anche se i gestori di eventi a lunga esecuzione sono comuni, puoi prendere in considerazione altre parti dell'interazione. Una parte precede la durata dell'elaborazione, nota come ritardo dell'input. Si tratta del tempo che intercorre tra l'avvio dell'interazione da parte dell'utente e il momento in cui i callback del gestore di eventi iniziano a essere eseguiti e si verificano quando il thread principale sta già elaborando un'altra attività. La build di attribuzione della libreria di vitali web può indicare la durata del ritardo di input per un'interazione:

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {inputDelay} = attribution; // 125.59439536
});

Se noti che alcune interazioni presentano ritardi di input elevati, devi capire che cosa stava accadendo nella pagina al momento dell'interazione che ha causato il lungo ritardo di input e che spesso si riduce a se l'interazione si è verificata durante il caricamento della pagina o in un secondo momento.

Durante il caricamento della pagina,

Il thread principale è spesso più trafficato durante il caricamento di una pagina. Durante questo periodo, tutti i tipi di attività vengono messi in coda ed elaborati e se l'utente prova a interagire con la pagina mentre è in corso questo lavoro, l'interazione potrebbe ritardare. Le pagine che caricano molto codice JavaScript possono iniziare a compilare e valutare gli script, oltre a eseguire funzioni che preparano una pagina alle interazioni degli utenti. Queste operazioni possono ostacolare il processo se l'utente interagisce con l'attività e puoi scoprire se è così per gli utenti del tuo sito web:

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {inputDelay} = attribution; // 125.59439536

  // Get the longest script from the first LoAF entry:
  const loaf = attribution.longAnimationFrameEntries[0];
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  if (script) {
    // Invoker types can describe if script eval blocked the main thread:
    const {invokerType} = script;    // 'classic-script' | 'module-script'
    const {sourceLocation} = script; // 'https://example.com/app.js'
  }
});

Se registri questi dati sul campo e noti ritardi nell'input e tipi di callout elevati ('classic-script' o 'module-script'), gli script sul tuo sito impongono molto tempo per essere valutati e bloccano il thread principale per un tempo sufficiente a ritardare le interazioni. Puoi ridurre questo tempo di blocco suddividendo gli script in pacchetti più piccoli, posticipare il caricamento del codice inizialmente inutilizzato in un secondo momento e verificare l'eventuale presenza di codice inutilizzato che puoi rimuovere completamente sul tuo sito.

Dopo il caricamento della pagina?

Sebbene si verifichino spesso ritardi durante l'inserimento di una pagina durante il caricamento di una pagina, è altrettanto possibile che si verifichino dopo il caricamento di una pagina, a causa di una causa completamente diversa. Le cause comuni dei ritardi nell'input dopo il caricamento della pagina possono essere il codice che viene eseguito periodicamente a causa di una chiamata setInterval precedente o anche i callback di eventi che erano in coda per essere eseguiti in precedenza e sono ancora in fase di elaborazione.

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {inputDelay} = attribution; // 125.59439536

  // Get the longest script from the first LoAF entry:
  const loaf = attribution.longAnimationFrameEntries[0];
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  if (script) {
    const {invokerType} = script;        // 'user-callback'
    const {sourceURL} = script;          // 'https://example.com/app.js'
    const {sourceCharPosition} = script; // 83
    const {sourceFunctionName} = script; // 'update'
  }
});

Come nel caso della risoluzione dei problemi relativi ai valori di durata di elaborazione elevata, gli elevati ritardi di input dovuti alle cause sopra menzionate forniranno dati di attribuzione dello script dettagliati. La differenza, tuttavia, è che il tipo di callback cambia in base alla natura dell'opera che ha ritardato l'interazione:

  • 'user-callback' indica che l'attività di blocco proveniva da setInterval, setTimeout o persino requestAnimationFrame.
  • 'event-listener' indica che l'attività di blocco proveniva da un input precedente che era in coda e ancora in fase di elaborazione.
  • 'resolve-promise' e 'reject-promise' indica che l'attività di blocco è stata generata da un'attività asincrona avviata in precedenza e risolta o rifiutata nel momento in cui l'utente ha tentato di interagire con la pagina, ritardando così l'interazione.

In ogni caso, i dati di attribuzione dello script ti daranno un'idea di dove iniziare a cercare e se il ritardo di input è dovuto al tuo codice o a quello di uno script di terze parti.

Ritardi nella presentazione lunghi

I ritardi di presentazione corrispondono all'ultimo chilometro di un'interazione e iniziano al termine dei gestori di eventi dell'interazione, fino al punto in cui è stato visualizzato il frame successivo. Si verificano quando l'opera in un gestore di eventi a causa di un'interazione cambia lo stato visivo dell'interfaccia utente. Come per la durata dell'elaborazione e i ritardi nell'input, la libreria degli elementi vitali web può indicare la durata del ritardo di presentazione per un'interazione:

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {presentationDelay} = attribution; // 113.32307691
});

Se registri questi dati e noti ritardi elevati nella presentazione per le interazioni che contribuiscono all'INP del tuo sito web, le cause possono variare, ma ecco un paio di cause da tenere d'occhio.

Lavoro di stile e layout costosi

Ritardi di presentazione lunghi possono comportare costosi lavori di ricalcolo dello stile e layout derivanti da una serie di cause, tra cui complessi selettori CSS e DOM di grandi dimensioni. Puoi misurare la durata di questa operazione con i tempi LoAF presenti nella libreria dei vitali web:

import {onINP} from 'web-vitals/attribution';

onINP(({name, value, attribution}) => {
  const {presentationDelay} = attribution; // 113.32307691

  // Get the longest script from the last LoAF entry:
  const loaf = attribution.longAnimationFrameEntries.at(-1);
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  // Get necessary timings:
  const {startTime} = loaf; // 2120.5
  const {duration} = loaf;  // 1002

  // Figure out the ending timestamp of the frame (approximate):
  const endTime = startTime + duration; // 3122.5

  // Get the start timestamp of the frame's style/layout work:
  const {styleAndLayoutStart} = loaf; // 3011.17692309

  // Calculate the total style/layout duration:
  const styleLayoutDuration = endTime - styleAndLayoutStart; // 111.32307691

  if (script) {
    // Get attribution for the event handler that triggered
    // the long-running style and layout operation:
    const {invokerType} = script;        // 'event-listener'
    const {invoker} = script;            // 'BUTTON#update.onclick'
    const {sourceURL} = script;          // 'https://example.com/app.js'
    const {sourceCharPosition} = script; // 83
    const {sourceFunctionName} = script; // 'update'
  }
});

LoAF non indicherà la durata del lavoro di stile e layout relativo a un fotogramma, ma ti indicherà quando è iniziato. Con questo timestamp di inizio, puoi utilizzare altri dati della LoAF per calcolare una durata precisa di quell'opera determinando l'ora di fine del frame e sottraendo da quella il timestamp di inizio del lavoro di stile e layout.

Callback di requestAnimationFrame a lunga esecuzione

Una potenziale causa di lunghi ritardi nella presentazione è il lavoro eccessivo svolto in un callback requestAnimationFrame. I contenuti di questo callback vengono eseguiti al termine dell'esecuzione dei gestori di eventi, ma appena prima del ricalcolo dello stile e delle operazioni di layout.

Il completamento di questi callback può richiedere molto tempo se il lavoro svolto al loro interno è complesso. Se sospetti che valori elevati di ritardo della presentazione siano dovuti al lavoro che stai svolgendo con requestAnimationFrame, puoi utilizzare i dati LoAF visualizzati dalla libreria degli elementi vitali web per identificare questi scenari:

onINP(({name, value, attribution}) => {
  const {presentationDelay} = attribution; // 543.1999999880791

  // Get the longest script from the last LoAF entry:
  const loaf = attribution.longAnimationFrameEntries.at(-1);
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  // Get the render start time and when style and layout began:
  const {renderStart} = loaf;         // 2489
  const {styleAndLayoutStart} = loaf; // 2989.5999999940395

  // Calculate the `requestAnimationFrame` callback's duration:
  const rafDuration = styleAndLayoutStart - renderStart; // 500.59999999403954

  if (script) {
    // Get attribution for the event handler that triggered
    // the long-running requestAnimationFrame callback:
    const {invokerType} = script;        // 'user-callback'
    const {invoker} = script;            // 'FrameRequestCallback'
    const {sourceURL} = script;          // 'https://example.com/app.js'
    const {sourceCharPosition} = script; // 83
    const {sourceFunctionName} = script; // 'update'
  }
});

Se noti che una parte significativa del ritardo della presentazione viene spesa in un callback requestAnimationFrame, assicurati che il lavoro che stai svolgendo con questi callback sia limitato all'esecuzione di operazioni che portino a un aggiornamento effettivo dell'interfaccia utente. Qualsiasi altro lavoro che non tocchi il DOM o aggiorni gli stili causerà inutilmente un ritardo nella colorazione del frame successivo, quindi fai attenzione.

Conclusione

I dati dei campi sono la migliore fonte di informazioni da cui attingere per capire quali interazioni sono problematiche per gli utenti reali sul campo. Utilizzando gli strumenti di raccolta dei dati sul campo come la libreria JavaScript degli eventi web-vital (o un provider RUM), puoi essere più sicuro di quali siano le interazioni più problematiche, quindi passare alla riproduzione di interazioni problematiche nel lab e quindi correggerle.

Immagine hero di Unsplash, di Federico Respini.