評估服務工作站的實際效能影響

服務工作者 (至少從效能角度而言) 最重大的好處之一,就是能夠主動控制資產快取。如果網頁應用程式可以快取所有必要的資源,則應可大幅加快回訪者的載入速度。不過,這些成果對實際使用者來說,實際上是什麼樣子?您又如何評估這項指標?

Google I/O 網頁應用程式 (簡稱 IOWA) 是漸進式網頁應用程式,可運用服務工作者提供的大部分新功能,為使用者提供豐富的應用程式體驗。他們也使用 Google Analytics 擷取大量多元使用者族群的主要成效資料和使用模式。

本案例研究探討 IOWA 如何使用 Google Analytics 找出關鍵成效問題的答案,並回報 service worker 的實際影響。

從問題開始

在網站或應用程式中導入數據分析時,請務必先從收集的資料中找出您想解答的問題。

我們有幾個想回答的問題,但為了配合本案例研究的目的,我們將著重於兩個較有趣的問題。

1. 服務工作者快取的效能是否比所有瀏覽器中現有的 HTTP 快取機制更佳?

我們預期回訪者網頁的載入速度會比新訪者網頁快,因為瀏覽器可將要求儲存在快取中,並在使用者再次造訪時立即提供。

服務工作者提供其他快取功能,讓開發人員精細控管快取的內容和方式。在 IOWA 中,我們改善了服務工作者實作方式,讓每項素材資源都會快取,讓回訪者可在完全離線的情況下使用應用程式。

但這項工作是否比瀏覽器預設功能更優異?如果是的話,效能提升了多少?1

2. 服務工作者會如何影響網站載入體驗?

換句話說,無論實際載入時間如何 (根據傳統網頁載入指標評估),網站的載入速度是否「感覺」很快?

回答有關體驗感受的問題當然不容易,而且沒有任何指標能完美呈現這種主觀感受。不過,有些指標確實比其他指標更適合,因此選擇正確的指標非常重要。

選擇合適的指標

根據預設,Google Analytics 會追蹤網站 1% 訪客的網頁載入時間 (透過 Navigation Timing API),並透過「平均網頁載入時間」等指標提供這些資料。

平均網頁載入時間 指標可用來回答第一個問題,但無法回答第二個問題。首先,load 事件不一定會與使用者實際與應用程式互動的時刻相符。此外,兩個載入時間完全相同的應用程式,在使用者體驗上可能會有很大差異。舉例來說,如果網站有啟動畫面或載入指標,使用者可能會覺得載入速度比只顯示空白畫面幾秒鐘的網站快上許多。

在 IOWA 中,我們顯示了啟動畫面倒數動畫,在應用程式背景載入其他內容的同時,這項功能 (在我看來) 非常成功地為使用者帶來娛樂。因此,追蹤啟動畫面顯示的時間長度,會是評估感知載入效能的最佳方式。我們選擇首次顯示時間這個指標來取得這個值。

決定要回答的問題,並找出有助於回答這些問題的指標後,就可以導入 Google Analytics 並開始評估。

Analytics 導入

如果您曾使用過 Google Analytics,可能就熟悉建議的 JavaScript 追蹤程式碼片段。這是訂閱按鈕的圖示:

<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<script async src="https://www.google-analytics.com/analytics.js"></script>

上述程式碼的第一行會初始化全域 ga() 函式 (如果尚未存在),而最後一行會以非同步方式下載 analytics.js 程式庫。

中間部分包含以下兩行:

ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');

這兩個指令可追蹤造訪網站的使用者瀏覽哪些網頁,但不會提供其他資訊。如果您想追蹤其他使用者互動,必須自行進行。

針對 IOWA,我們想追蹤另外兩項資訊:

  • 從網頁開始載入到畫面顯示像素所經過的時間。
  • 是否由 Service Worker 控管網頁。有了這項資訊,我們就能區隔報表,比較有無服務工作元的結果。

擷取首次顯示所需時間

部分瀏覽器會記錄第一個像素繪製到畫面上的確切時間,並將這段時間提供給開發人員。與透過 Navigation Timing API 公開的 navigationStart 值相比,這個值可讓我們非常精確地計算出,從使用者最初要求存取網頁到首次看到內容所需的時間。

如先前所述,首次繪製時間是重要的評估指標,因為這是使用者體驗網站載入速度的起點。這是使用者對品牌的第一印象,良好的第一印象可以為後續的使用者體驗帶來正面影響2

為了在瀏覽器中取得第一個顯示的值,我們建立了 getTimeToFirstPaintIfSupported 公用程式函式:

function getTimeToFirstPaintIfSupported() {
  // Ignores browsers that don't support the Performance Timing API.
  if (window.performance && window.performance.timing) {
    var navTiming = window.performance.timing;
    var navStart = navTiming.navigationStart;
    var fpTime;

    // If chrome, get first paint time from `chrome.loadTimes`.
    if (window.chrome && window.chrome.loadTimes) {
      fpTime = window.chrome.loadTimes().firstPaintTime * 1000;
    }
    // If IE/Edge, use the prefixed `msFirstPaint` property.
    // See http://msdn.microsoft.com/ff974719
    else if (navTiming.msFirstPaint) {
      fpTime = navTiming.msFirstPaint;
    }

    if (fpTime && navStart) {
      return fpTime - navStart;
    }
  }
}

有了這個,我們現在可以編寫另一個函式,傳送非互動事件,並將首次繪製的時間設為其值:3

function sendTimeToFirstPaint() {
  var timeToFirstPaint = getTimeToFirstPaintIfSupported();

  if (timeToFirstPaint) {
    ga('send', 'event', {
      eventCategory: 'Performance',
      eventAction: 'firstpaint',
      // Rounds to the nearest millisecond since
      // event values in Google Analytics must be integers.
      eventValue: Math.round(timeToFirstPaint)
      // Sends this as a non-interaction event,
      // so it doesn't affect bounce rate.
      nonInteraction: true
    });
  }
}

編寫這兩個函式後,追蹤程式碼會如下所示:

// Creates the tracker object.
ga('create', 'UA-XXXXX-Y', 'auto');

// Sends a pageview for the initial pageload.
ga('send', 'pageview');

// Sends an event with the time to first paint data.
sendTimeToFirstPaint();

請注意,視上述程式碼執行的時間而定,畫素可能已繪製到螢幕上,也可能尚未繪製。為確保系統一開始繪製時就會執行這段程式碼,我們將對 sendTimeToFirstPaint() 的呼叫延後至 load 事件之後。事實上,我們決定將所有數據分析資料的傳送作業延後至網頁載入完成後,以確保這些要求不會與其他資源的載入作業競爭。

// Creates the tracker object.
ga('create', 'UA-XXXXX-Y', 'auto');

// Postpones sending any hits until after the page has fully loaded.
// This prevents analytics requests from delaying the loading of the page.
window.addEventListener('load', function() {
  // Sends a pageview for the initial pageload.
  ga('send', 'pageview');

  // Sends an event with the time to first paint data.
  sendTimeToFirstPaint();
});

上述程式碼會向 Google Analytics 回報 firstpaint 次,但這只是一半的資訊。我們仍需追蹤 Service Worker 狀態,否則無法比較 Service Worker 控管的網頁和未控管網頁的首次繪製時間。

判斷 Service worker 狀態

為了判斷服務工作者的目前狀態,我們建立了一個公用函式,會傳回下列三個值之一:

  • 受控管:Service Worker 正在控管網頁。在 IOWA 的情況下,這也表示所有素材資源都已快取,且網頁可在離線狀態下運作。
  • 支援:瀏覽器支援 Service Worker,但 Service Worker 尚未控制網頁。這是初次造訪者的預期狀態。
  • 不支援:使用者的瀏覽器不支援服務工作者。
function getServiceWorkerStatus() {
  if ('serviceWorker' in navigator) {
    return navigator.serviceWorker.controller ? 'controlled' : 'supported';
  } else {
    return 'unsupported';
  }
}

這個函式會為我們取得服務工作者狀態;接下來,我們要將這個狀態與傳送至 Google Analytics 的資料建立關聯。

使用自訂維度追蹤自訂資料

根據預設,Google Analytics 提供許多方法,讓您根據使用者、工作階段或互動的屬性,將總流量細分為多個群組。這些屬性稱為「維度」。網路開發人員常會關注的維度包括「瀏覽器」、「作業系統」或「裝置類別」

服務工作者的狀態並非 Google Analytics 預設提供的維度,但您可以自行建立自訂維度,並視需要加以定義。

針對 IOWA,我們建立了名為「Service Worker Status」的自訂維度,並將其範圍設為「hit」(即每個互動)。4您在 Google Analytics 中建立的每個自訂維度都會在該資源中獲得專屬索引,您可以在追蹤程式碼中透過索引參照該維度。舉例來說,如果我們剛建立的維度索引為 1,我們可以更新邏輯,如下所示,以便傳送 firstpaint 事件,納入服務工作者狀態:

ga('send', 'event', {
  eventCategory: 'Performance',
  eventAction: 'firstpaint',
  // Rounds to the nearest millisecond since
  // event values in Google Analytics must be integers.
  eventValue: Math.round(timeToFirstPaint)
  // Sends this as a non-interaction event,
  // so it doesn't affect bounce rate.
  nonInteraction: true,

  // Sets the current service worker status as the value of
  // `dimension1` for this event.
  dimension1: getServiceWorkerStatus()
});

這麼做是可行的,但只會將服務工作單元的狀態與這個特定事件建立關聯。Service Worker 狀態對於任何互動都可能有用,因此最好將其納入傳送至 Google Analytics 的所有資料。

為在所有回應 (例如所有網頁瀏覽、事件等) 中加入這項資訊,我們會在追蹤器 物件本身上設定自訂維度值,然後再將任何資料傳送至 Google Analytics。

ga('set', 'dimension1', getServiceWorkerStatus());

設定完成後,系統會在目前網頁載入的所有後續命中中傳送這個值。如果使用者稍後再次載入網頁,系統可能會從 getServiceWorkerStatus() 函式傳回新的值,並在追蹤器物件上設定該值。

關於程式碼的清晰度和可讀性,請注意:其他查看此程式碼的使用者可能不知道 dimension1 是指什麼,因此建議您建立變數,將有意義的維度名稱對應至 analytics.js 會使用的值。

// Creates a map between custom dimension names and their index.
// This is particularly useful if you define lots of custom dimensions.
var customDimensions = {
  SERVICE_WORKER_STATUS: 'dimension1'
};

// Creates the tracker object.
ga('create', 'UA-XXXXX-Y', 'auto');

// Sets the service worker status on the tracker,
// so its value is included in all future hits.
ga('set', customDimensions.SERVICE_WORKER_STATUS, getServiceWorkerStatus());

// Postpones sending any hits until after the page has fully loaded.
// This prevents analytics requests from delaying the loading of the page.
window.addEventListener('load', function() {
  // Sends a pageview for the initial pageload.
  ga('send', 'pageview');

  // Sends an event with the time to first paint data.
  sendTimeToFirstPaint();
});

如前所述,您可以透過每個命中傳送「Service Worker Status」維度,讓我們在製作任何指標報表時使用這項維度。

如您所見,IOWA 的所有網頁瀏覽次數中,有近 85% 來自支援 Service Worker 的瀏覽器。

結果:解答我們的問題

開始收集資料以回答問題後,我們就能根據這些資料製作報表,查看結果。(注意:此處顯示的所有 Google Analytics 資料,代表 2016 年 5 月 16 日至 22 日期間,IOWA 網站的實際網站流量)。

我們首先想知道:服務工作者快取功能的效能是否優於所有瀏覽器現有的 HTTP 快取機制?

為回答這個問題,我們建立了自訂報表,針對不同維度查看「平均網頁載入時間」指標。這項指標非常適合用來回答這個問題,因為只有在所有初始資源下載完成後,load 事件才會觸發。因此,這項指標直接反映所有網站重要資源的總載入時間。5

我們選擇的維度如下:

  • 我們的自訂「Service Worker Status」維度。
  • 使用者類型:指出使用者是首次造訪網站,還是回訪網站。(注意:新訪客不會有任何快取資源,但回訪者可能會有)。
  • 裝置類別:可比較行動版和電腦版的結果。

為避免非 Service Worker 相關因素影響載入時間結果,我們將查詢限制在僅包含支援 Service Worker 的瀏覽器。

如您所見,由 Service Worker 控管的應用程式造訪比未控管的造訪載入速度快上許多,即使是來自已快取大部分網頁資源的回訪使用者,也是如此。值得注意的是,平均而言,使用服務工作者的行動裝置訪客,比使用桌機的訪客更快載入網頁。

「…當由 Service Worker 控管的應用程式造訪次數,比未控管的造訪次數載入速度快上許多…

如需更多詳細資訊,請參閱下列兩個表格:

平均網頁載入時間 (桌機)
Service Worker 狀態 使用者類型 平均網頁載入時間 (豪秒) 樣本數量
控管 回訪者 2568 30860
支援 回訪者 3612 1289
支援 新訪客 4664 21991
平均網頁載入時間 (行動裝置)
Service Worker 狀態 使用者類型 平均網頁載入時間 (豪秒) 樣本數量
控管 回訪者 3760 8162
支援 回訪者 4843 676
支援 新訪客 6158 5779

您可能會想知道,如果回訪者使用的瀏覽器支援 Service Worker,為何會處於未受控狀態。可能的原因如下:

  • 使用者在初次造訪時離開網頁,Service Worker 還沒機會完成初始化。
  • 使用者透過開發人員工具解除安裝服務工作者。

這兩種情況都比較少見。我們可以查看第四欄中的「Page Load Sample」值,瞭解資料中的相關資訊。請注意,中間的資料列樣本數量遠低於其他兩列。

第二個問題是:服務工作者會如何影響網站載入體驗?

為了回答這個問題,我們為指標「平均事件價值」建立了另一份自訂報表,並篩選結果,只納入 firstpaint 事件。我們使用了「裝置類別」維度和自訂的「Service Worker 狀態」維度。

與我預期的結果相反,行動裝置上的服務工作者對首次繪製時間的影響,比整體網頁載入時間還要小。

「…行動版服務工作者對首次繪製時間的影響,遠低於對整體網頁載入時間的影響。」

為了瞭解原因,我們必須進一步分析資料。平均值可用於一般概況和大略概述,但要真正瞭解這些數字如何在不同使用者之間細分,我們需要查看 firstpaint 次的時間分布。

在 Google Analytics 中取得指標的分配

如要取得 firstpaint 次數的分布情形,我們需要存取每個事件的個別結果。很抱歉,Google Analytics 無法輕鬆完成這項作業。

Google Analytics 可讓我們依照所需維度細分報表,但無法依據指標細分報表。這並非表示無法實現,而是表示我們必須進一步自訂導入方式,才能取得理想結果。

由於報表結果只能依維度細分,因此我們必須將指標值 (在本例中為 firstpaint 時間) 設為事件的自訂維度。為此,我們建立了另一個名為「Metric Value」的自訂維度,並更新 firstpaint 追蹤邏輯,如下所示:

var customDimensions = {
  SERVICE_WORKER_STATUS: 'dimension1',
  <strong>METRIC_VALUE: 'dimension2'</strong>
};

// ...

function sendTimeToFirstPaint() {
  var timeToFirstPaint = getTimeToFirstPaintIfSupported();

  if (timeToFirstPaint) {
    var fields = {
      eventCategory: 'Performance',
      eventAction: 'firstpaint',
      // Rounds to the nearest millisecond since
      // event values in Google Analytics must be integers.
      eventValue: Math.round(timeToFirstPaint)
      // Sends this as a non-interaction event,
      // so it doesn't affect bounce rate.
      nonInteraction: true
    }

    <strong>// Sets the event value as a dimension to allow for breaking down the
    // results by individual metric values at reporting time.
    fields[customDimensions.METRIC_VALUE] = String(fields.eventValue);</strong>

    ga('send', 'event', fields);
  }
}

Google Analytics 網頁版介面目前無法提供任意指標值的視覺化呈現,但我們可以利用 Google Analytics Core Reporting APIGoogle 圖表程式庫,查詢原始結果,然後自行建立直方圖。

舉例來說,下列 API 要求設定可用於在電腦上透過未控管的服務工作者取得 firstpaint 值的分布。

{
  dateRanges: [{startDate: '2016-05-16', endDate: '2016-05-22'}],
  metrics: [{expression: 'ga:totalEvents'}],
  dimensions: [{name: 'ga:dimension2'}],
  dimensionFilterClauses: [
    {
      operator: 'AND',
      filters: [
        {
          dimensionName: 'ga:eventAction',
          operator: 'EXACT',
          expressions: ['firstpaint']
        },
        {
          dimensionName: 'ga:dimension1',
          operator: 'EXACT',
          expressions: ['supported']
        },
        {
          dimensionName: 'ga:deviceCategory',
          operator: 'EXACT',
          expressions: ['desktop']
        }
      ],
    }
  ],
  orderBys: [
    {
      fieldName: 'ga:dimension2',
      orderType: 'DIMENSION_AS_INTEGER'
    }
  ]
}

這個 API 要求會傳回值陣列,如下所示 (注意:這只是前五個結果)。結果會從最小到最大排序,因此這些列代表最快的時間。

API 回應結果 (前五列)
ga:dimension2 ga:totalEvents
4 3
5 2
6 10
7 8
8 10

以下是這些結果的簡單說明:

  • 有 3 個事件的 firstpaint 值為 4 毫秒
  • 有 2 個事件的 firstpaint 值為 5 毫秒
  • 有 10 個事件的 firstpaint 值為 6 毫秒
  • 有 8 個事件的 firstpaint 值為 7 毫秒
  • 有 10 個事件的 firstpaint value 為 8 毫秒
  • 其他

我們可以根據這些結果推算每個事件的 firstpaint 值,並建立分布直方圖。我們對每個執行的查詢都執行這項操作。

以下是電腦上使用未控管 (但支援) 的 Service Worker 時,發布情形如下:

電腦上首次顯示所需時間分布情況 (支援)

上述分布的 firstpaint 中位時間為 912 毫秒

這條曲線的形狀是負載時間分布的典型形狀。請比較下方的直方圖,該圖顯示服務工作者控制網頁時,首次繪製事件的分布情形。

電腦上首次顯示所需時間分布情況 (控制組)

請注意,當 Service Worker 控制網頁時,許多訪客都會立即看到第一個畫面,平均時間為 583 毫秒

「…當 Service Worker 控制網頁時,許多訪客都會立即看到第一個 Paint 作業…

為了讓您更瞭解這兩種分布的差異,下圖顯示兩者的合併檢視畫面。顯示未受控服務 worker 造訪次數的直方圖,會疊加在顯示受控造訪次數的直方圖上方,而這兩者會疊加在顯示兩者總和的直方圖上方。

電腦版的首次顯示時間分布情形

我發現這些結果有個有趣之處,就是在初始尖峰後,使用受控服務工作的分布仍呈現鐘形曲線。我預期最初會出現大幅度的尖峰,然後逐漸下降,並沒有預期曲線會出現第二個高峰。

在調查可能造成這個問題的原因時,我發現即使 Service Worker 可以控制網頁,但其執行緒可能處於停用狀態。瀏覽器會這麼做的原因是為了節省資源 - 您不需要每個造訪過的網站都啟用服務工作者,讓服務工作者隨時都能運作。這就是分布圖尾端的情況。部分使用者在服務工作者執行緒啟動時,會發生延遲現象。

不過,從分布圖中可以看到,即使有這段初始延遲時間,使用服務工作者的瀏覽器仍比透過網路的瀏覽器更快地傳送內容。

以下是行動版的顯示方式:

行動版的首次顯示時間分布情形

雖然我們仍大幅提升了近乎即時的首次顯示時間,但尾端的時間卻變得更長。這可能是因為在行動裝置上啟動空閒服務 worker 執行緒的時間,比在電腦上啟動所需的時間還要長。這也說明瞭為何平均 firstpaint 時間的差異沒有我預期的明顯 (如上所述)。

「在行動裝置上,啟動閒置服務 worker 執行緒的時間比在電腦上長。」

以下是行動版和電腦版的首繪時間中位數平均值,並依服務工作者狀態分組:

畫面首次顯示所需時間中位數 (毫秒)
Service Worker 狀態 電腦 行動裝置
控管 583 1634
支援 (未控制) 912 1933

雖然建立這些發布示意圖比在 Google Analytics 中建立自訂報表耗費的時間和心力多一點,但這比單純查看平均值更能讓我們瞭解服務工作者對網站效能的影響。

Service Worker 的其他影響

除了效能影響之外,服務工作者也會以其他方式影響使用者體驗,這些影響可透過 Google Analytics 進行評估。

離線存取

Service Worker 可讓使用者在離線時與您的網站互動,雖然某些離線支援功能對任何漸進式網路應用程式都非常重要,但在您的情況下,這項功能的重要性取決於離線使用量。但我們要如何評估這項指標呢?

傳送資料給 Google Analytics 需要連上網際網路,但不需要在互動發生的確切時間傳送資料。Google Analytics 支援在事後傳送互動資料,方法是指定時間偏移 (透過 qt 參數)。

過去兩年,IOWA 一直使用服務工作者指令碼,在使用者離線時偵測 Google Analytics 的失敗命中,並稍後透過 qt 參數重播這些命中。

為了追蹤使用者是否處於線上或離線狀態,我們建立了名為「Online」的自訂維度,並將其設為 navigator.onLine 的值,然後監聽 onlineoffline 事件,並據此更新維度。

為了瞭解使用者在使用 IOWA 時,離線的頻率有多高,我們建立了一個區隔,鎖定至少有一次離線互動的使用者。結果發現,這類使用者約占 5%。

推播通知

服務工作者可讓使用者選擇接收推播通知。在 IOWA 中,使用者會在行事曆中即將開始的會議時收到通知。

無論是哪種形式的通知,都必須在提供價值和避免打擾使用者之間取得平衡。為了進一步瞭解發生哪種情況,請務必追蹤使用者是否選擇接收這些通知、是否在抵達時與通知互動,以及先前選擇接收通知的使用者是否變更偏好設定並選擇不接收。

在 IOWA 中,我們只會傳送與使用者個人化時間表相關的通知,而這類內容只有已登入的使用者才能建立。這項限制會將可接收通知的使用者限制在已登入的使用者 (透過名為「已登入」的自訂維度追蹤),且瀏覽器必須支援推播通知 (透過另一個名為「通知權限」的自訂維度追蹤)。

以下報表是根據指標「使用者」和「通知權限」自訂維度,以區隔出在某個時間點登入且瀏覽器支援推播通知的使用者。

很高興看到登入的使用者中有半數以上選擇接收推播通知。

應用程式安裝橫幅

如果漸進式網頁應用程式符合條件,且使用者經常使用,系統可能會向使用者顯示應用程式安裝橫幅,提示他們將應用程式新增到主畫面。

在 IOWA 中,我們使用以下程式碼追蹤這些提示向使用者顯示的頻率 (以及使用者是否接受提示):

window.addEventListener('beforeinstallprompt', function(event) {
  // Tracks that the user saw a prompt.
  ga('send', 'event', {
    eventCategory: 'installprompt',
    eventAction: 'fired'
  });

  event.userChoice.then(function(choiceResult) {
    // Tracks the users choice.
    ga('send', 'event', {
      eventCategory: 'installprompt',
      // `choiceResult.outcome` will be 'accepted' or 'dismissed'.
      eventAction: choiceResult.outcome,
      // `choiceResult.platform` will be 'web' or 'android' if the prompt was
      // accepted, or '' if the prompt was dismissed.
      eventLabel: choiceResult.platform
    });
  });
});

在看到應用程式安裝橫幅的使用者中,約 10% 選擇將應用程式新增至主畫面。

可能的追蹤改善方式 (下次可參考)

我們今年從 IOWA 收集到的分析資料非常寶貴。但事後總是能發現漏洞,並有助於在下次執行時改善。完成今年的分析後,我發現有兩個地方可以改進,希望有意採用類似策略的讀者可以參考:

1. 追蹤更多與載入體驗相關的事件

我們追蹤了幾個與技術指標相對應的事件 (例如 HTMLImportsLoadedWebComponentsReady 等),但由於大部分的載入作業都是非同步執行,因此這些事件觸發的時機不一定與整體載入體驗中的特定時刻相對應。

我們未追蹤的主要載入相關事件 (但希望能追蹤) 是啟動畫面消失,使用者可看到網頁內容的時間點。

2. 將 Analytics 用戶端 ID 儲存在 IndexedDB 中

根據預設,analytics.js 會在瀏覽器的 Cookie 中儲存 Client-ID 欄位;但可惜的是,Service Worker 指令碼無法存取 Cookie。

這會導致我們在嘗試導入通知追蹤功能時發生問題。我們希望每次向使用者傳送通知時,都能透過評估資料協定從服務工作者傳送事件,然後在使用者點選通知並返回應用程式時,追蹤該通知的再參與成效。

雖然我們可以透過 utm_source 廣告活動參數追蹤通知的成功率,但無法將特定再參與活動階段與特定使用者建立關聯。

我們可以透過 IndexedDB 在追蹤程式碼中儲存用戶端 ID,藉此解決這項限制,這樣服務工作者指令碼就能存取該值。

3. 讓 Service worker 回報線上/離線狀態

檢查 navigator.onLine 可讓您瞭解瀏覽器是否能連線至路由器或區域網路,但不一定能讓您瞭解使用者是否有實際連線。由於離線數據分析服務 worker 指令碼只會重播失敗的命中 (不會修改或標示為失敗),因此我們可能低估了離線使用量。

日後,我們應同時追蹤 navigator.onLine 的狀態,以及系統是否因初始網路故障而由服務工作者重播命中。這麼做有助於我們更準確地掌握實際的離線使用情形。

總結

本案例研究顯示,使用服務工作者確實可改善 Google I/O 網頁應用程式在多種瀏覽器、網路和裝置上的載入效能。研究也顯示,當您查看各式各樣瀏覽器、網路和裝置的載入資料分布情形時,就能更深入瞭解這項技術如何處理實際情境,並發現您可能未預期到的效能特徵。

以下是 IOWA 研究的幾項重要發現:

  • 平均來說,在 Service Worker 控制網頁的情況下,網頁的載入速度會比沒有 Service Worker 時快上許多,這一點在新訪客和回訪者身上都適用。
  • 許多使用者造訪由 Service Worker 控管的網頁時,幾乎立即載入。
  • 服務工作站在閒置時,需要花一點時間才能啟動。不過,停用的 Service Worker 仍比沒有 Service Worker 的情況下表現更好。
  • 閒置服務 worker 在行動裝置上的啟動時間比在電腦上的啟動時間長。

雖然在特定應用程式中觀察到的成效提升通常有助於向更廣大的開發人員社群回報,但請務必記住,這些結果是針對 IOWA 的網站類型 (活動網站) 和目標對象類型 (主要是開發人員) 而得出的。

如果您在應用程式中導入服務工作者,請務必實作自己的評估策略,以便評估自己的成效,並防止日後的回歸現象。如果你有,請分享你的結果,讓所有人都能受惠!

註釋

  1. 比較服務工作者快取導入作業的效能,與僅使用 HTTP 快取的網站效能,並不公平。由於我們是為了服務工作者而最佳化 IOWA,因此並未花費太多時間進行 HTTP 快取最佳化。如果我們有,結果可能會有所不同。如要進一步瞭解如何針對 HTTP 快取最佳化網站,請參閱「有效地最佳化內容」。
  2. 視網站載入樣式和內容的方式而定,瀏覽器可能會在內容或樣式可用之前進行繪製。在這種情況下,firstpaint 可能會對應到空白畫面。如果您使用 firstpaint,請務必確保該事件與網站資源載入過程中的有意義點相符。
  3. 從技術層面來說,我們可以傳送時間記錄 (預設為非互動),擷取這項資訊,而非事件。事實上,Google Analytics 中的時間戳記是專門用來追蹤這類載入指標;不過,時間戳記會在處理期間大量取樣,因此其值無法用於區隔。考量目前的限制,非互動事件仍是較佳的選擇。
  4. 如要進一步瞭解在 Google Analytics 中設定自訂維度的範圍,請參閱 Analytics 說明中心的「自訂維度」一節。您也必須瞭解 Google Analytics 資料模型,其中包含使用者、工作階段和互動 (命中)。如要進一步瞭解,請觀看 Analytics Academy 的 Google Analytics 資料模型課程
  5. 這不會計算在載入事件後延後載入的資源。