本文件尚未涵蓋的一個 Workbox 模組是 workbox-window
,這是一組預計在 window
中執行的模組。本單元的目標如下:
- 協助開發人員識別服務 Worker 生命週期的關鍵時刻,進而簡化服務工作處理程序的註冊和更新流程,更輕鬆地在適當情況下回應工作人員。
- 為了避免開發人員犯常見錯誤,例如註冊位於錯誤範圍內的 Service Worker。
- 簡化
window
和Service Worker 範圍之間的訊息傳遞作業。
匯入及使用 workbox-window
最常用的匯出項目是 workbox-window
中的 Workbox
類別,您可以透過節點或從網頁的 CDN 匯入。
建立本機套件
如果工具鍊含有 webpack 或 Rollup 等整合工具,您就可以在本機封裝 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 更新可更新時通知使用者。該方案會使用名為 messageSkipWaiting
的 self.skipWaiting
特殊輔助方法,而它會傳送 type
值為 SKIP_WAITING
的訊息。