Service Worker 註冊

安排服務工作人員註冊時間的最佳做法。

服務工作站可以有效加快重複造訪網頁應用程式的速度,但您應採取步驟,確保 Service Worker 的初次安裝作業不會對使用者的首次造訪體驗造成負面影響。

一般而言,在第一個頁面載入完成後,再延遲 Service Worker 註冊,可為使用者提供最佳體驗,特別是在網路連線速度較慢的行動裝置使用者。

常見註冊樣板

如果您曾閱讀過 Service Worker,可能會發現樣板與以下內容十分相似:

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js');
}

有時可能會附帶一些 console.log() 陳述式或程式碼,用於偵測先前 Service Worker 註冊的更新內容,藉此讓使用者知道重新整理頁面。但這些只是標準幾行程式碼的細微變化

那麼,navigator.serviceWorker.register 是否有任何細微差異?是否有任何可以遵循的最佳做法?不出乎意料 (因為這篇文章並未立即結束),因此無論如何回答「是!」

使用者首次造訪

讓我們考量使用者首次造訪網頁應用程式的情形。目前還沒有服務工作站,且瀏覽器無法事先得知最終會安裝的服務工作站。

開發人員應優先確保瀏覽器快速取得顯示互動式頁面所需的最低限度重要資源。任何會拖慢擷取回應速度的任何作業,都是速度更快的互動體驗。

現在,假設您在下載網頁需要轉譯的 JavaScript 或圖片的過程中,瀏覽器決定啟動背景執行緒或程序 (為求簡潔,我們會假設它是執行緒)。假設您使用的不是桌上型電腦,而是世界上大多數人將採用低功耗行動電話的類型視為主要裝置。啟動這個額外執行緒會增加瀏覽器在轉譯互動式網頁時,可能會用到的 CPU 時間和記憶體爭用情形。

閒置的背景執行緒不太可能帶來顯著差異。但如果該執行緒並未處於閒置狀態,而是判定也會開始從網路下載資源,該怎麼辦?任何關於 CPU 或記憶體爭用情形的疑慮,都應避免擔心多數行動裝置可用的頻寬有限。頻寬相當寶貴,所以不要同時下載次要資源,從而降低關鍵資源的效能。

也就是說,如果希望在使用者首次造訪網站時,為他們提供最短互動時間,可以啟動新的 Service Worker 執行緒來在背景中下載資源並快取資源,這可能不是問題。

改善樣板

解決方案是透過選擇呼叫 navigator.serviceWorker.register() 的時機來控制 Service Worker 的啟動時間。有一個簡單的原則就是將登錄延遲到 window 上的 load event 啟動,例如:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js');
    });
}

但是啟動服務工作站註冊的適當時機,也可以取決於網頁應用程式載入後正在執行的動作。例如,Google I/O 2016 網頁應用程式會在轉換至主畫面前產生簡短的動畫。我們的團隊發現在動畫期間啟動 Service Worker 註冊作業,可能會導致低階行動裝置上的資源浪費。系統不會給予使用者不良體驗,而是將服務工作站註冊延遲到動畫播放為止,但瀏覽器很可能處於閒置秒數。

同樣地,如果網頁應用程式使用的架構會在網頁載入完成後執行其他設定,請尋找在作業完成後發出信號的架構專屬事件。

後續造訪

截至目前為止,我們一直將重心放在初次造訪體驗上,但延遲服務工作人員註冊對網站重複造訪有何影響? 雖然可能會讓某些人感到驚訝,但不會受到任何影響。

Service Worker 完成註冊後會經過 installactivate 生命週期事件。啟用 Service Worker 後,即可針對任何後續造訪網頁應用程式的 fetch 事件處理 fetch 事件。Service Worker 會先啟動「之前」,才能對範圍內的所有網頁提出要求。也就是說,這對你來說很合理。如果現有的 Service Worker 在造訪網頁前就尚未執行,可能就無法執行導覽要求的 fetch 事件。

因此,在有使用中的 Service Worker 時,您都沒有關係,或是呼叫 navigator.serviceWorker.register() 時,您甚至不需要呼叫該 Worker。除非您變更 Service Worker 指令碼的網址,否則在後續造訪期間,navigator.serviceWorker.register() 實際上就是「免人工管理」。這名稱不相關時

提前註冊的原因

盡早註冊 Service Worker 的任何情況都合理嗎?請記住,服務工作站在第一次造訪時使用 clients.claim() 控制網頁,而服務工作站會在其 fetch 處理常式內積極執行執行階段快取。在這類情況下,為了盡快啟用 Service Worker,有利於嘗試在執行階段快取中填入稍後可能會派上用場的資源。假使您的網頁應用程式屬於這個類別,建議您返回確認,服務工作站的 install 處理常式不會要求使用資源來解決主頁面要求而爭用頻寬的資源。

測試

如要模擬首次造訪的情況,在 Chrome 無痕式視窗中開啟網頁應用程式,然後在 Chrome 開發人員工具中查看網路流量,是不錯的做法。身為網頁程式開發人員,可能每天重新載入網頁應用程式的本機執行個體數十次和數十次。但是當有 Service Worker 且已填入完整快取的情況下,請重新造訪您的網站,讓您獲得的體驗與新使用者的體驗不同,很容易忽略潛在的問題。

以下範例說明註冊時間可能的差異。使用網路節流功能透過無痕模式造訪範例應用程式時,系統會擷取這兩個螢幕截圖,以便模擬緩慢連線。

提前註冊的網路流量。

上方螢幕截圖反映了修改樣本時的網路流量,以盡快執行 Service Worker 註冊。您可以看到預先快取要求 (來自服務工作站的 install 處理常式所發出的齒輪圖示) 與顯示頁面所需的其他資源要求交錯。

末期註冊的網路流量。

在上方螢幕截圖中,Service Worker 的註冊作業已延遲到頁面載入後才進行。您可以看到預先快取要求直到所有資源都從網路擷取後才會啟動,因此可消除頻寬的任何爭用。此外,由於我們預先快取的部分項目已存在於瀏覽器的 HTTP 快取中,也就是「大小」欄中含有 (from disk cache) 的項目,因此您不必再次前往網路,即可填入服務工作站的快取。

如果您是在真實的行動網路上透過真實的低階裝置執行這類測試,就能獲得獎勵積分。您可以善用 Chrome 的遠端偵錯功能,透過 USB 將 Android 手機連接至桌上型電腦,確保您執行的測試確實能反映許多使用者的實際體驗。

結論

總而言之,確保使用者享有最佳的首次造訪體驗是首要之務。將服務工作站的註冊作業延後到頁面在初次造訪期間載入後才進行,有助於確保註冊作業順利進行。但您還是能享有 安排服務工作人員的重複造訪所帶來的所有好處

如要確保將 Service Worker 的初始註冊延遲到第一個頁面載入後才完成,您可以使用以下指令:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js');
    });
}