修正版面配置不穩定性

使用 WebPageTest 找出及修正版面配置不穩定問題的逐步操作說明。

我在之前的文章中,提到了「測量 WebPageTest 中的累計版面配置位移」(CLS)。CLS 集結了所有版面配置位移,因此在這篇文章中,我認為建議您深入探究並檢查網頁上的每個版面配置位移,嘗試瞭解造成不穩定的原因,並實際嘗試修正問題。

測量版面配置位移

透過 Layout Instability API,我們可以取得頁面上的所有版面配置位移事件清單:

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

這會產生一個陣列,且前方沒有輸入事件:版面配置位移:

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

在本例中,只有 0.01% 的 210 毫秒十分微幅變動,

掌握偏移情形的時間和嚴重程度,有助於找出造成偏移的可能原因。讓我們返回研究室環境的 WebPageTest 進行更多測試。

在 WebPageTest 中測量版面配置位移

與在 WebPageTest 中評估 CLS 類似,評估個別版面配置位移需要使用自訂指標。幸好,Chrome 77 穩定版,這個流程變得更簡單了。Layout Instability API 預設為啟用,因此您應該在 Chrome 77 版的任何網站中執行該 JS 程式碼片段,並立即取得結果。在 WebPageTest 中,您可以使用預設的 Chrome 瀏覽器,不必擔心指令列旗標或使用 Canary。

讓我們修改該指令碼,為 WebPageTest 產生自訂指標:

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

此指令碼中的承諾會解析為陣列的 JSON 表示法,而非陣列本身。這是因為自訂指標只能產生字串或數字等基本資料類型。

我打算用來測試網站 ismyhostfastyet.com,這是我為了比較網站主機實際載入效能而建置的網站。

找出版面配置不穩定的原因

結果中,可看到 LayoutShifts 自訂指標的值如下:

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

總結來說,在 3087 毫秒時,單一版面配置位移為 34.2%。為協助找出問題的原因,讓我們使用 WebPageTest 的幻燈片檢視畫面

幻燈片中的兩個儲存格,顯示版面配置位移前後的螢幕截圖。
幻燈片中的兩個儲存格,顯示版面配置位移前後的螢幕截圖。

捲動至幻燈片中的 3 秒左右,即可確實瞭解 34% 版面配置位移的原因:彩色表格。網站會以非同步方式擷取 JSON 檔案,然後算繪為資料表。該資料表一開始沒有任何內容,因此在載入結果時等待表格填滿,就會轉移位移。

網路字型標頭未顯示。
網頁字型標頭未顯示在這裡。

除此之外,當網頁完成檢視時間約為 4.3 秒時,即可看到「我的主機還快嗎?」網頁的 <h1> 未顯示在這裡。這是因為網站使用網路字型,但尚未採取任何步驟最佳化轉譯功能。在此情況下,版面配置實際上不會移動,但若遲遲無法閱讀標題,使用者體驗仍然不甚理想。

修正版面配置不穩定問題

現在,我們已瞭解非同步產生的資料表會導致三分之一的可視區域偏移,接下來就是要加以修正。除非實際載入 JSON 結果,否則我們不知道表格內容,但我們仍可在資料表中填入一些預留位置資料,以便在 DOM 轉譯時讓版面配置本身保持相對穩定。

以下是產生預留位置資料的程式碼:

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'));

系統會在排序前隨機產生預留位置資料。其中「█」字元會隨機重複次數來建立視覺預留位置,並建立三個主要值。我還新增了一些樣式來讓表格中所有顏色的飽和度降低,更清楚地瞭解資料尚未完全載入。

使用的預留位置外觀不會影響版面配置穩定性。這個預留位置的用途是確保使用者瞭解內容「是」,且網頁不會損毀。

以下是在 JSON 資料載入期間顯示的預留位置:

資料表會以預留位置資料轉譯。
資料表會以預留位置資料轉譯。

解決網路字型問題會簡單許多。這個網站使用 Google Fonts,因此我們只需要在 CSS 要求中傳入 display=swap 屬性。就這樣,Fonts API 會在字型宣告中加入 font-display: swap 樣式,讓瀏覽器立即顯示備用字型的文字。以下是修正後的對應標記:

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

驗證最佳化

透過 WebPageTest 重新執行網頁後,我們就能產生前後對照的比較資料,以視覺化方式呈現兩者的差異,並評估版面配置的不穩定度:

WebPageTest 幻燈片顯示兩個網站並排載入,不論是否經過版面配置最佳化。
WebPageTest 幻燈片顯示兩個網站並排載入,以及沒有版面配置最佳化的網站。
[
  {
    "name": "",
    "entryType": "layout-shift",
    "startTime": 3070.9349999997357,
    "duration": 0,
    "value": 0.000050272187989256116,
    "hadRecentInput": false,
    "lastInputTime": 0
  }
]

根據自訂指標,由於 3071 毫秒仍發生版面配置位移 (與先前相同),但位移嚴重性大幅縮小:0.005%。那我就住了。

也可從幻燈片中清楚看出,<h1> 字型會立即改回系統字型,讓使用者可以更快閱讀。

結語

相較於這個範例,複雜的網站可能會出現更多版面配置變更情形,但修復程序仍保持不變:將版面配置不穩定的指標加入 WebPageTest、與視覺載入幻燈片交叉比對結果,藉此找出問題,並且使用預留位置來預留螢幕空間。

(還有一項努力) 評估實際使用者遇到版面配置不穩定的情況

想在網頁最佳化前後執行 WebPageTest 是很好的事,但真正重要的是使用者體驗確實越來越進步。我們不是一開始就努力讓網站更臻完善嗎?

因此,我們會開始評估實際使用者的版面配置不穩定體驗,搭配傳統的網頁成效指標,這也是最佳化回饋循環中的關鍵部分,因為透過從該數據資料判斷問題出在哪,以及我們的修正是否帶來正面影響。

除了收集您自己的版面配置不穩定的資料外,您還可以參閱 Chrome 使用者體驗報告,其中含有來自數百萬個網站的實際使用者體驗累計版面配置位移資料。這項工具可讓您瞭解自己 (或競爭對手) 的成效,或探索網路上不穩定的版面配置狀態。