Correggere l'instabilità del layout

Una procedura dettagliata per l'utilizzo di WebPageTest per identificare e risolvere i problemi di instabilità del layout.

In un post precedente ho scritto sulla misurazione del Cumulative Layout Shift (CLS) in WebPageTest. Il CLS è un'aggregazione di tutte le variazioni del layout, quindi in questo post ho pensato che sarebbe stato interessante approfondire e ispezionare ogni singola variazione di layout in una pagina per cercare di capire cosa potrebbe causare l'instabilità e provare effettivamente a risolvere i problemi.

Misurazione delle variazioni del layout

Utilizzando l'API Layout Instability, possiamo ottenere un elenco di tutti gli eventi di variazione del layout su una pagina:

new Promise(resolve => {
  new PerformanceObserver(list => {
    resolve(list.getEntries().filter(entry => !entry.hadRecentInput));
  }).observe({type: "layout-shift", buffered: true});
}).then(console.log);

Questo produce un array di variazioni del layout che non sono precedute da eventi di input:

[
  {
    "name": "",
    "entryType": "layout-shift",
    "startTime": 210.78500000294298,
    "duration": 0,
    "value": 0.0001045969445437389,
    "hadRecentInput": false,
    "lastInputTime": 0
  }
]

In questo esempio c’è stato un singolo spostamento molto ridotto dello 0,01% a 210 ms.

Conoscere l'ora e la gravità del turno è utile per identificare meglio cosa potrebbe aver causato il cambiamento. Torniamo a WebPageTest per un ambiente lab per eseguire altri test.

Misurazione delle variazioni del layout in WebPageTest

Analogamente alla misurazione del CLS in WebPageTest, la misurazione delle singole variazioni del layout richiede una metrica personalizzata. Fortunatamente, la procedura è più semplice ora che Chrome 77 è stabile. L'API Layout Instability è attivata per impostazione predefinita, pertanto dovresti essere in grado di eseguire lo snippet JS su qualsiasi sito web in Chrome 77 e ottenere immediatamente i risultati. In WebPageTest, puoi utilizzare il browser Chrome predefinito senza preoccuparti dei flag della riga di comando o dell'uso di Canary.

Ora modifichiamo lo script in modo da produrre una metrica personalizzata per WebPageTest:

[LayoutShifts]
return new Promise(resolve => {
  new PerformanceObserver(list => {
    resolve(JSON.stringify(list.getEntries().filter(entry => !entry.hadRecentInput)));
  }).observe({type: "layout-shift", buffered: true});
});

La promessa in questo script si risolve in una rappresentazione JSON dell'array anziché dell'array stesso. Questo perché le metriche personalizzate possono produrre solo tipi di dati primitivi come stringhe o numeri.

Il sito web che userò per il test è ismyhostfastyet.com, un sito che ho creato per confrontare le prestazioni di caricamento degli host web nel mondo reale.

Identificazione delle cause dell'instabilità del layout

Nei risultati, puoi vedere che la metrica personalizzata LayoutShifts ha questo valore:

[
  {
    "name": "",
    "entryType": "layout-shift",
    "startTime": 3087.2349999990547,
    "duration": 0,
    "value": 0.3422101449275362,
    "hadRecentInput": false,
    "lastInputTime": 0
  }
]

Per riassumere, c'è un singolo cambiamento del layout del 34,2% a 3087 ms. Per identificare il colpevole, usiamo la visualizzazione sequenza di WebPageTest.

Due celle nella sequenza, che mostrano screenshot prima e dopo la variazione del layout.
Due celle nella pellicola, che mostrano screenshot prima e dopo la variazione del layout.

Scorrendo fino all'indicatore di circa 3 secondi nella sequenza, si può vedere esattamente qual è la causa di questa variazione del layout del 34%: la tabella colorata. Il sito web recupera in modo asincrono un file JSON e lo visualizza in una tabella. La tabella è inizialmente vuota, quindi attendere di riempirla quando vengono caricati i risultati causa lo spostamento.

L'intestazione del carattere web appare dal nulla.
L'intestazione del carattere web appare dal nulla.

Ma non solo. Quando la pagina è visivamente completa a circa 4,3 secondi, possiamo vedere che il <h1> della pagina "Is my host fast already?" (Il mio host è ancora veloce?) appare dal nulla. Questo accade perché il sito utilizza un carattere web e non ha adottato misure per ottimizzare il rendering. In realtà il layout non sembra cambiare, ma dover aspettare così a lungo prima di leggere il titolo rappresenta un'esperienza utente scadente.

Correzione dell'instabilità del layout

Ora che sappiamo che la tabella generata in modo asincrono causa lo spostamento di un terzo dell'area visibile, è il momento di risolvere il problema. Non conosciamo i contenuti della tabella finché i risultati JSON non vengono effettivamente caricati, ma possiamo comunque completare la tabella con un qualche tipo di dati segnaposto in modo che il layout stesso sia relativamente stabile quando viene visualizzato il DOM.

Ecco il codice per generare dati segnaposto:

function getRandomFiller(maxLength) {
  var filler = '█';
  var len = Math.ceil(Math.random() * maxLength);
  return new Array(len).fill(filler).join('');
}

function getRandomDistribution() {
  var fast = Math.random();
  var avg = (1 - fast) * Math.random();
  var slow = 1 - (fast + avg);
  return [fast, avg, slow];
}

// Temporary placeholder data.
window.data = [];
for (var i = 0; i < 36; i++) {
  var [fast, avg, slow] = getRandomDistribution();
  window.data.push({
    platform: getRandomFiller(10),
    client: getRandomFiller(5),
    n: getRandomFiller(1),
    fast,
    avg,
    slow
  });
}
updateResultsTable(sortResults(window.data, 'fast'));

I dati relativi ai segnaposto vengono generati in modo casuale prima di essere ordinati. Include il carattere "█" ripetuto un numero casuale di volte per creare segnaposto visivi per il testo, nonché una distribuzione casuale dei tre valori principali. Ho anche aggiunto alcuni stili per desaturare tutti i colori dalla tabella per chiarire che i dati non sono ancora stati caricati completamente.

L'aspetto dei segnaposto utilizzati non è importante per la stabilità del layout. Lo scopo dei segnaposto è garantire agli utenti che i contenuti saranno disponibili e che la pagina non sarà interrotta.

Ecco l'aspetto dei segnaposto durante il caricamento dei dati JSON:

La tabella di dati viene visualizzata con i dati segnaposto.
La tabella di dati viene visualizzata con i dati dei segnaposto.

Affrontare il problema dei caratteri web è molto più semplice. Poiché il sito usa i caratteri Google Fonts, dobbiamo solo passare la proprietà display=swap nella richiesta CSS. È tutto. L'API Fonts aggiungerà lo stile font-display: swap nella dichiarazione dei caratteri, consentendo al browser di visualizzare immediatamente il testo in un carattere di riserva. Ecco il markup corrispondente con la correzione inclusa:

<link href="https://fonts.googleapis.com/css?family=Chivo:900&display=swap" rel="stylesheet">

Verifica delle ottimizzazioni

Dopo aver eseguito di nuovo la pagina tramite WebPageTest, possiamo generare un confronto prima e dopo per visualizzare la differenza e misurare il nuovo grado di instabilità del layout:

Pellicola WebPageTest che mostra il caricamento di entrambi i siti affiancati con e senza ottimizzazioni del layout.
Pellicola WebPageTest che mostra entrambi i siti che vengono caricati fianco a fianco con e senza ottimizzazioni del layout.
[
  {
    "name": "",
    "entryType": "layout-shift",
    "startTime": 3070.9349999997357,
    "duration": 0,
    "value": 0.000050272187989256116,
    "hadRecentInput": false,
    "lastInputTime": 0
  }
]

Secondo la metrica personalizzata, c'è ancora una variazione del layout che si verifica a 3071 ms (circa lo stesso tempo di prima), ma la gravità della variazione è molto inferiore: 0,005%. Posso farne uso.

Dalla sequenza è chiaro anche che il carattere <h1> torna subito a un carattere di sistema, consentendo agli utenti di leggerlo più rapidamente.

Conclusione

I siti web complessi probabilmente riscontreranno molte più variazioni del layout rispetto a questo esempio, ma il processo di correzione è rimasto lo stesso: aggiungi metriche di instabilità del layout a WebPageTest, esegui un controllo incrociato dei risultati con la sequenza di caricamento visiva per identificare i colpevoli e implementa una correzione utilizzando i segnaposto per prenotare lo spazio sullo schermo.

(Un'ultima cosa) Misurare l'instabilità del layout sperimentata da utenti reali

È bello poter eseguire WebPageTest su una pagina prima e dopo un'ottimizzazione e vedere un miglioramento di una metrica, ma ciò che conta davvero è che l'esperienza utente migliora effettivamente. Non è per questo che stiamo cercando di migliorare il sito?

Sarebbe bello se iniziassimo a misurare le esperienze di instabilità del layout di utenti reali insieme alle nostre tradizionali metriche sul rendimento sul web. Si tratta di un aspetto cruciale del ciclo di feedback dell'ottimizzazione, perché i dati sul campo ci indicano dove sono i problemi e se le nostre correzioni hanno fatto una differenza positiva.

Oltre a raccogliere i tuoi dati sull'instabilità del layout, dai un'occhiata al report sull'esperienza utente di Chrome, che include i dati Cumulative Layout Shift derivanti da esperienze utente reali su milioni di siti web. Ti consente di conoscere il tuo rendimento o quello della concorrenza oppure puoi utilizzarlo per esaminare lo stato di instabilità del layout sul web.