偵錯欄位效能

瞭解如何使用偵錯資訊來歸因效能資料,協助您透過數據分析找出並修正使用者的實際問題

Google 提供兩種成效評估及偵錯工具:

  • 研究室工具:Lighthouse 等工具。Lighthouse 等工具會在模擬環境中載入網頁,而該環境會模仿各種條件 (例如網路速度緩慢和低階行動裝置)。
  • 現場工具:例如 Chrome 使用者體驗報告 (CrUX) 這類工具,是以 Chrome 的匯總實際使用者資料為基礎。(請注意,PageSpeed InsightsSearch Console 等工具回報的欄位資料來自 CrUX 資料。)

雖然現場工具可提供更準確的資料 (實際資料反映了實際使用者體驗的資料),但研究室工具通常更能協助您找出及修正問題。

CrUX 資料更能代表網頁的實際效能,但瞭解 CrUX 分數無法協助您找出改善效能的「方法」

另一方面,Lighthouse 會找出問題,並提供具體改善建議。不過,Lighthouse 只會針對網頁載入時發現的效能問題提供建議。但無法偵測僅因使用者互動而引發的問題 (例如網頁上的捲動或點擊按鈕)。

這意味著一個重要問題是:如何擷取 Core Web Vitals 指標的偵錯資訊,或實際使用者的其他效能指標?

這篇文章將詳細說明您可以使用哪些 API,針對目前的 Core Web Vitals 指標收集其他偵錯資訊,並提供在現有分析工具中擷取這類資料的相關概念。

用於歸因和偵錯的 API

累計版面配置位移 (CLS)

在所有 Core Web Vitals 指標中,CLS 可能是最重要的指標,因為您必須在實地收集偵錯資訊。CLS 是整個網頁生命週期的評估依據,因此使用者與網頁的互動方式 (捲動距離、點擊的內容等) 可能會對是否有版面配置位移以及哪些元素位移產生重大影響。

請參考下列 PageSpeed Insights 報告:

含有不同 CLS 值的 PageSpeed Insights 報表
PageSpeed Insights 會顯示欄位和研究室資料 (如果有的話,這些資料可能不同)

實驗室 (Lighthouse) 回報的 CLS 值與實地 (CrUX 資料) 回報的 CLS 值相當不同,但這很合理,因為網頁可能含有許多互動內容,但在 Lighthouse 中測試時並未使用。

但即使您瞭解使用者互動會影響欄位資料,您還是需要知道頁面中哪些元素在第 75 個百分位數會經過轉變,導致 0.28 的分數達到 0.28。只要使用 LayoutShiftAttribution 介面,即可達成這項目標。

取得版面配置位移歸因

Layout Instability API 發出的每個 layout-shift 項目上,都會顯示 LayoutShiftAttribution 介面。

如需這兩種介面的詳細說明,請參閱「偵錯版面配置變更」。就本篇文章而言,您需要瞭解的主要事項是,身為開發人員,您可以觀察頁面上發生的每個版面配置變動,以及變動的元素。

以下程式碼範例會記錄每個版面配置位移以及移動的元素:

new PerformanceObserver((list) => {
  for (const {value, startTime, sources} of list.getEntries()) {
    // Log the shift amount and other entry info.
    console.log('Layout shift:', {value, startTime});
    if (sources) {
      for (const {node, curRect, prevRect} of sources) {
        // Log the elements that shifted.
        console.log('  Shift source:', node, {curRect, prevRect});
      }
    }
  }
}).observe({type: 'layout-shift', buffered: true});

在每次發生單一版面配置位移時,測量資料並傳送至分析工具可能並不實用;不過,您可以透過監控所有位移追蹤最差的位移,只回報這些位移的相關資訊。

目標並非找出並修正每位使用者發生的每個版面配置位移,而是找出影響最多使用者的位移,進而對頁面 75 百分位數的 CLS 產生最大影響。

此外,您不需要在每次出現轉換時都計算最大的來源元素,只要在準備將 CLS 值傳送至分析工具時才需要這麼做。

以下程式碼取得了對 CLS 有貢獻的 layout-shift 項目,並從最大偏移值傳回最大的來源元素:

function getCLSDebugTarget(entries) {
  const largestEntry = entries.reduce((a, b) => {
    return a && a.value > b.value ? a : b;
  });
  if (largestEntry && largestEntry.sources && largestEntry.sources.length) {
    const largestSource = largestEntry.sources.reduce((a, b) => {
      return a.node && a.previousRect.width * a.previousRect.height >
          b.previousRect.width * b.previousRect.height ? a : b;
    });
    if (largestSource) {
      return largestSource.node;
    }
  }
}

找出造成最大變動幅度最大的元素後,便可向數據分析工具回報該指標。

影響特定網頁 CLS 的元素可能因使用者而異,但如果您匯總所有使用者的這些元素,就能產生影響最多使用者的變動元素清單。

找出並修正這些元素的變動根本原因後,您的數據分析程式碼就會開始將較小的變動,視為網頁的「最糟」變動來回報。最後,所有回報的變動幅度都會夠小,讓你的網頁遠離「良好」門檻

以下是與最大位移來源元素一起拍攝的其他中繼資料:

  • 最大轉移時間
  • 最大移位時的網址路徑 (適用於動態更新網址的網站,例如單頁面應用程式)。

最大內容繪製 (LCP)

如要在實驗室中偵錯 LCP,您需要的主要資訊是,在該網頁載入期間,哪個特定元素是最大的元素 (LCP 候選元素)。

請注意,即使是同一個網頁,使用者之間的 LCP 候選元素也可能不同,這在實際上相當常見。

問題的原因如下:

  • 使用者的裝置螢幕解析度各異,因此會產生不同的網頁版面配置,進而導致可視區域內顯示不同的元素。
  • 使用者不一定會載入捲動至最頂端的網頁。連結通常會包含片段 ID,甚至是文字片段,因此網頁可能會在網頁上的任何捲動位置載入並顯示。
  • 內容可能會針對目前使用者進行個人化,因此 LCP 候選元素可能會因使用者而異。

也就是說,您無法假設哪個元素或元素組合會是特定網頁最常見的 LCP 候選元素。您必須根據實際使用者的行為進行評估。

找出 LCP 候選元素

如要在 JavaScript 中判斷 LCP 候選元素,您可以使用 Largest Contentful Paint API,也就是用來判斷 LCP 時間值的 API。

觀察 largest-contentful-paint 項目時,您可以透過查看最後一個項目的 element 屬性,判斷目前的 LCP 候選元素:

new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const lastEntry = entries[entries.length - 1];

  console.log('LCP element:', lastEntry.element);
}).observe({type: 'largest-contentful-paint', buffered: true});

瞭解 LCP 候選元素後,即可將其連同指標值一併傳送至分析工具。這項指標與 CLS 相同,可協助您找出最需要優先最佳化的元素。

除了 LCP 候選元素以外,評估 LCP 子部分的時間也非常實用,有助於確定與網站相關的具體最佳化步驟。

與下一個顯示的內容互動 (INP)

在 INP 欄位中需要擷取的最重要資訊如下:

  1. 使用者與哪個元素互動
  2. 為什麼會有互動類型?
  3. 互動發生的時間

互動速度緩慢的主因是主執行緒遭到封鎖,在 JavaScript 載入期間可能很常見。瞭解大部分的互動速度緩慢情形是否發生在網頁載入期間,有助於判斷需要採取哪些措施來解決問題。

INP 指標會考量互動的完整延遲時間,包括執行任何已註冊事件監聽器所需的時間,以及執行所有事件監聽器後繪製下一個影格所需的時間。也就是說,對於 INP 來說,瞭解哪些目標元素容易導致互動速度變慢,以及這些互動類型非常重要。

下列程式碼會記錄 INP 項目的目標元素和時間。

function logINPDebugInfo(inpEntry) {
  console.log('INP target element:', inpEntry.target);
  console.log('INP interaction type:', inpEntry.name);
  console.log('INP time:', inpEntry.startTime);
}

請注意,此程式碼不會顯示如何判斷哪個 event 項目是 INP 項目,因為該邏輯較為複雜。不過,下一節將說明如何使用 web-vitals JavaScript 程式庫取得這項資訊。

搭配 web-vitals JavaScript 程式庫使用

前幾節提供了一些一般建議和程式碼範例,讓您擷取偵錯資訊並納入數據分析工具的資料中。

自第 3 版起,web-vitals JavaScript 程式庫包含會顯示所有相關資訊的「歸因建構」,以及一些其他信號

以下程式碼範例說明如何設定額外的事件參數 (或自訂維度),其中包含可協助找出效能問題根本原因的偵錯字串。

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

function sendToGoogleAnalytics({name, value, id, attribution}) {
  const eventParams = {
    metric_value: value,
    metric_id: id,
  }

  switch (name) {
    case 'CLS':
      eventParams.debug_target = attribution.largestShiftTarget;
      break;
    case 'LCP':
      eventParams.debug_target = attribution.element;
      break;
    case 'INP':
      eventParams.debug_target = attribution.interactionTarget;
      break;
  }

  // Assumes the global `gtag()` function exists, see:
  // https://developers.google.com/analytics/devguides/collection/ga4
  gtag('event', name, eventParams);
}

onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);

這段程式碼專供 Google Analytics 使用,但一般概念也適用於其他分析工具。

這段程式碼也只是說明如何回報單一偵錯信號,但如果能夠針對每個指標收集及回報多個不同的信號,就會很有幫助。

舉例來說,如要對 INP 進行偵錯,您可能需要收集互動元素、互動類型、時間、loadState、互動階段等資訊 (例如 Long Animation Frame 資料)。

web-vitals 歸因版本會顯示其他歸因資訊,如以下範例 INP 所示:

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

function sendToGoogleAnalytics({name, value, id, attribution}) {
  const eventParams = {
    metric_value: value,
    metric_id: id,
  }

  switch (name) {
    case 'INP':
      eventParams.debug_target = attribution.interactionTarget;
      eventParams.debug_type = attribution.interactionType;
      eventParams.debug_time = attribution.interactionTime;
      eventParams.debug_load_state = attribution.loadState;
      eventParams.debug_interaction_delay = Math.round(attribution.inputDelay);
      eventParams.debug_processing_duration = Math.round(attribution.processingDuration);
      eventParams.debug_presentation_delay =  Math.round(attribution.presentationDelay);
      break;

    // Additional metric logic...
  }

  // Assumes the global `gtag()` function exists, see:
  // https://developers.google.com/analytics/devguides/collection/ga4
  gtag('event', name, eventParams);
}

onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);

如需完整的偵錯信號公開清單,請參閱 web-vitals 歸因說明文件

製作資料報表並以視覺化方式呈現

開始收集偵錯資訊和指標值後,下一步就是匯總所有使用者的資料,以便開始搜尋模式和趨勢。

如前文所述,您不一定需要解決使用者遇到的每一個問題,建議您優先解決影響最多使用者的問題,而這些問題對於 Core Web Vitals 分數的影響最大。

如要瞭解如何使用 BigQuery 查詢及視覺化呈現資料,請參閱 GA4 專屬文章如何使用 BigQuery 查詢及視覺化呈現資料

摘要

希望本文已概述如何使用現有效能 API 和 web-vitals 程式庫取得偵錯資訊,以根據實際使用者造訪現場的造訪情況診斷效能。雖然本指南著重於 Core Web Vitals,但這些概念也適用於偵錯任何可在 JavaScript 中評估的成效指標。

如果您剛開始評估成效,且已是 Google Analytics 使用者,建議您先使用 Web Vitals 報表工具,因為這項工具已支援回報 Core Web Vitals 指標的偵錯資訊。

如果您是分析服務供應商,且想要改善產品並為使用者提供更多偵錯資訊,請考慮本文所述的一些技巧,但不侷限於這裡介紹的想法。本文內容適用於所有數據分析工具,不過,各個分析工具或許 (也應該) 可能會 (也應該) 擷取並回報更多偵錯資訊。

最後,如果您認為 API 缺少功能或資訊,導致無法偵錯這些指標,請將意見回饋傳送至 web-vitals-feedback@googlegroups.com