偵錯欄位效能

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

Google 提供兩類工具,可用於評估及偵錯效能:

  • 實驗室工具: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。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 的元素可能因使用者而異,但如果您匯總所有使用者的這些元素,就能產生影響最多使用者的變動元素清單。

找出並修正這些元素的變動根本原因後,您的數據分析程式碼就會開始將較小的變動,視為網頁的「最糟」變動來回報。最終,所有回報的轉移都會縮小到足以讓網頁落在0.1 的「良好」門檻以下

除了最大轉換來源元素之外,您可能還想擷取以下其他中繼資料:

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

最大內容繪製 (LCP)

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

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

問題的原因如下:

  • 使用者的裝置螢幕解析度各異,因此會產生不同的網頁版面配置,進而導致可視區域內顯示不同的元素。
  • 使用者不一定會載入捲動至頂端的網頁。連結通常會包含片段識別碼,甚至是文字片段,這表示網頁可能會在任何捲動位置載入並顯示。
  • 內容可能會針對目前使用者進行個人化,因此 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 子部分時間,這有助於判斷網站需要哪些具體最佳化步驟。

Interaction to Next Paint (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