使用工作箱視窗

本文件尚未涵蓋的一個 Workbox 模組是 workbox-window,這是一組預計在 window 中執行的模組。本單元的目標如下:

  • 協助開發人員識別服務 Worker 生命週期的關鍵時刻,進而簡化服務工作處理程序的註冊和更新流程,更輕鬆地在適當情況下回應工作人員。
  • 為了避免開發人員犯常見錯誤,例如註冊位於錯誤範圍內的 Service Worker。
  • 簡化 windowService Worker 範圍之間的訊息傳遞作業。

匯入及使用 workbox-window

最常用的匯出項目是 workbox-window 中的 Workbox 類別,您可以透過節點或從網頁的 CDN 匯入。

建立本機套件

如果工具鍊含有 webpackRollup 等整合工具,您就可以在本機封裝 workbox-window

首先,請安裝 workbox-window,做為應用程式的實際工作環境依附元件:

npm install workbox-window --save

接著,在應用程式 JavaScript 中,您可以從 workbox-window import Workbox 類別:

<script type="module">
import {Workbox} from 'workbox-window';

if ('serviceWorker' in navigator) {
  const wb = new Workbox('/sw.js');

  wb.register();
}
</script>

雖然 workbox-window 的規模相當小,但你「可以」使用動態 import 將其與網站的核心應用程式邏輯分割,藉此縮減網頁主要套件的大小:

<script type="module">
if ('serviceWorker' in navigator) {
  const {Workbox} = await import('workbox-window');

  const wb = new Workbox('/sw.js');
  wb.register();
}
</script>

使用 CDN

雖然不建議使用 workbox-window,但更簡單的方式是從 CDN 匯入:

<script type="module">
  import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.2.0/workbox-window.prod.mjs';

  if ('serviceWorker' in navigator) {
    const wb = new Workbox('/sw.js');

    wb.register();
  }
</script>

您會注意到,上述範例中的 <script> 元素使用 type="module" 屬性。如要在無建構步驟的情況下,在瀏覽器中使用靜態 import 陳述式,就必須這麼做。所有支援 Service Worker 的主要瀏覽器也支援 JavaScript 模組,因此您可以將此程式碼提供給任何瀏覽器,因為舊版瀏覽器會忽略 type 屬性值為 "module"<script> 元素。

註冊 Service Worker

如要透過 workbox-window 註冊 Service Worker,可透過 Workbox 類別的 register 方法完成,如下所示:

import {Workbox} from 'workbox-window';

const wb = new Workbox('/sw.js');
wb.register();

似乎與使用 navigator.serviceWorker.register 自行註冊 Service Worker 相同。不過,Workbox.register 會等待 window load 事件,然後再註冊 Service Worker。這是在進行預先快取的情況下,可避免發生頻寬爭用情況,進而導致網頁啟動延遲的情形。

window 和 Service Worker 範圍之間進行通訊

Service Worker 的範圍與 window 不同,而且只能存取 window 中的部分 API。不過,window 和 Service Worker 之間還是可以進行通訊。workbox-window 可讓您使用 workbox-window 模組的 messageSW 方法,更輕鬆地在兩個範圍之間進行通訊。

Workbox 訊息特定格式是具備下列屬性的物件:

  • type 是必要字串,用於識別訊息。格式應為大寫,並以底線分隔字詞,例如 CACHE_URLS
  • meta 是選用字串,代表傳送訊息的 Workbox 套件名稱 (通常會省略)。
  • payload 是選用參數,代表要傳送的資料。可以是任何資料類型。

以下是 messageSW 運作方式的範例,從 Service Worker 中的程式碼開始:

// sw.js
const SW_VERSION = '1.0.0';

self.addEventListener('message', (event) => {
  if (event.data.type === 'GET_VERSION') {
    event.ports[0].postMessage(SW_VERSION);
  }
});

接著,在網頁上加入下列程式碼:

const wb = new Workbox('/sw.js');
wb.register();

const swVersion = await wb.messageSW({type: 'GET_VERSION'});
console.log('Service Worker version:', swVersion);

在許多執行個體中,在 Service Worker 和 window 之間進行通訊會很實用,例如,在有 Service Worker 更新可更新時通知使用者。該方案會使用名為 messageSkipWaitingself.skipWaiting 特殊輔助方法,而它會傳送 type 值為 SKIP_WAITING 的訊息。