提供意見回饋:一項實驗性回應指標

評估網站回應速度的計畫即將更新。

Hongbo Song
Hongbo Song

今年稍早,Chrome 速度指標團隊分享了我們在設計新回應速度指標時考慮的一些想法。我們希望設計一個能更準確擷取個別事件端對端延遲時間的指標,且能更全面地掌握網頁在整個生命週期內的整體回應速度。

過去幾個月來,我們在這項指標上取得了很大的進展,同時想與您分享我們預計如何評估互動延遲時間,並介紹一些我們計劃量化網頁整體回應速度的具體匯總選項。

我們很樂意收到開發人員和網站擁有者的意見回饋,瞭解這些選項最能代表他們網頁的整體輸入反應。

測量互動延遲時間

作為審查,「First Input Delay (FID)」指標會擷取輸入延遲時間的延遲部分。也就是說,從使用者與網頁互動到事件處理常式可執行所需的時間。

我們打算擴充這個新指標來擷取完整事件時間長度,從初始使用者輸入內容擷取到所有事件處理常式執行後繪製下一個影格為止。

此外,我們也打算評估互動,而非個別事件。互動是事件群組,會做為相同邏輯使用者手勢的一部分分派 (例如:pointerdownclickpointerup)。

為了評估一組個別事件持續時間的總互動延遲時間,我們將考慮採取下列兩種做法:

  • 事件持續時間上限:互動延遲時間等於互動群組中任何事件的最大單一事件持續時間。
  • 事件總持續時間:互動延遲是所有事件持續時間的總和 (忽略任何重疊)。

下圖舉例說明由 keydownkeyup 事件組成的按鍵互動。在本例中,這兩個事件之間的持續時間重疊。如要測量按鍵互動的延遲時間,可以使用 max(keydown duration, keyup duration)sum(keydown duration, keyup duration) - duration overlap

顯示以事件持續時間為依據的互動延遲時間的圖表

每種方法各有優缺點,而我們會想收集更多資料和意見回饋,再確定延遲定義。

匯總每個網頁的所有互動

在我們能夠評估所有互動的端對端延遲時間後,下一步就是定義網頁造訪的匯總分數,其中可能包含多次互動。

瀏覽了很多選項後,我們決定將選擇範圍縮小至下一節所述的策略,每種策略目前是在 Chrome 中收集實際使用者資料。有時間收集到足夠的資料後,我們計劃發布結果結果。不過,我們也希望能夠向網站擁有者直接提供意見回饋,幫助他們更準確地反映網頁互動模式。

匯總策略選項

為協助說明下列各項策略,請參考包含四種互動的範例網頁造訪:

互動技術 延遲時間
(按一下滑鼠) 120 毫秒
(按一下滑鼠) 20 毫秒
按鍵效果 60 毫秒
按鍵效果 80 毫秒

最差的互動延遲時間

網頁上發生的最大個別互動延遲時間。基於上述互動範例,最差的互動延遲時間為 120 毫秒。

預算策略

使用者體驗研究表明,使用者可能不會認為延遲時間低於特定門檻為負值。根據這項研究,我們考慮了幾項預算策略,這些策略各針對各個事件類型採用下列門檻:

互動類型 預算門檻
按一下/輕觸 100 毫秒
拖曳 100 毫秒
鍵盤 50 毫秒

每個策略都只考量超過每次互動的預算門檻。以上述網頁造訪範例來說,超預算金額會如下所示:

互動技術 延遲時間 延遲超出預算
按一下 120 毫秒 20 毫秒
按一下 20 毫秒 0 毫秒
按鍵 60 毫秒 10 毫秒
按鍵 80 毫秒 30 毫秒

與預算相關的最低互動延遲時間

在預算之外,最大的單一互動延遲時間。就上例而言,分數為 max(20, 0, 10, 30) = 30 ms

超出預算的總互動延遲時間

與預算相較下所有互動延遲的總和。就上例而言,分數為 (20 + 0 + 10 + 30) = 60 ms

超出預算的平均互動延遲時間

預算超額互動總延遲時間除以互動總數。在上述範例中,分數為 (20 + 0 + 10 + 30) / 4 = 15 ms

高分位數的近似值

除了預算之外,除了運算最大互動延遲時間之外,我們也考慮使用高分位數的近似值,這對於互動次數較多且可能具有大量離群值的網頁較為合適。我們發現了兩項可能的高四分位數概略策略:

  • 選項 1:在預算之外追蹤最大與第二大的互動情形。每 50 次新互動後,請捨棄上一組 50 次中的最大互動,並新增目前 50 組中的最大互動。最終價值則是比預算更多的剩餘互動次數。
  • 選項 2:計算在預算之外的前 10 項互動,並根據互動總數從清單中選擇一個值。對於總互動次數而言,請選取第 N/50 + 1 大 (N/50 + 1) 最大的值,或是針對互動超過 500 次的網頁選取第 10 個值。

在 JavaScript 中評估這些選項

以下程式碼範例可用來確定上述前三個策略的值。請注意,目前仍無法評估 JavaScript 中網頁上的互動總數,因此這個範例未包含預算策略或高四分位數概略策略的平均互動次數。

const interactionMap = new Map();

let worstLatency = 0;
let worstLatencyOverBudget = 0;
let totalLatencyOverBudget = 0;

new PerformanceObserver((entries) => {
  for (const entry of entries.getEntries()) {
    // Ignore entries without an interaction ID.
    if (entry.interactionId > 0) {
      // Get the interaction for this entry, or create one if it doesn't exist.
      let interaction = interactionMap.get(entry.interactionId);
      if (!interaction) {
        interaction = {latency: 0, entries: []};
        interactionMap.set(entry.interactionId, interaction);
      }
      interaction.entries.push(entry);

      const latency = Math.max(entry.duration, interaction.latency);
      worstLatency = Math.max(worstLatency, latency);

      const budget = entry.name.includes('key') ? 50 : 100;
      const latencyOverBudget = Math.max(latency - budget, 0);
      worstLatencyOverBudget = Math.max(
        latencyOverBudget,
        worstLatencyOverBudget,
      );

      if (latencyOverBudget) {
        const oldLatencyOverBudget = Math.max(interaction.latency - budget, 0);
        totalLatencyOverBudget += latencyOverBudget - oldLatencyOverBudget;
      }

      // Set the latency on the interaction so future events can reference.
      interaction.latency = latency;

      // Log the updated metric values.
      console.log({
        worstLatency,
        worstLatencyOverBudget,
        totalLatencyOverBudget,
      });
    }
  }
  // Set the `durationThreshold` to 50 to capture keyboard interactions
  // that are over-budget (the default `durationThreshold` is 100).
}).observe({type: 'event', buffered: true, durationThreshold: 50});

意見回饋:

我們希望鼓勵開發人員在自己的網站上試用這些全新的回應速度指標,如果發現任何問題,歡迎與我們聯絡。

如對本文所述方法有任何一般意見,請透過電子郵件寄至 web-vitals-feedback Google 群組,並在主旨行註明「[Responseness Metrics]」(回應式指標)。我們非常期待收到您的想法!