このドキュメントにはまだ記載されていない Workbox モジュールの一つに workbox-window
があります。これは、window
で実行することを目的としたモジュールのセットです。このモジュールの目標は次のとおりです。
- デベロッパーが Service Worker のライフサイクルにおける重要な瞬間を特定し、その瞬間に対応できるようにすることで、Service Worker の登録と更新を簡素化します。
- デベロッパーが誤ったスコープで Service Worker を登録するなど、よくあるミスを防ぐ。
window
と Service Worker スコープ間のメッセージングを簡素化するため。
workbox-window
のインポートと使用
workbox-window
から最も頻繁に使用するエクスポートは Workbox
クラスです。このクラスは、Node でインポートすることも、ウェブページの CDN からインポートすることもできます。
ローカル バンドルの作成
ツールチェーンに webpack や Rollup などのバンドラが含まれている場合は、workbox-window
をローカルでバンドルできます。
まず、workbox-window
をアプリケーションの本番環境の依存関係としてインストールします。
npm install workbox-window --save
次に、アプリケーションの JavaScript で、workbox-window
から Workbox
クラスを import
できます。
<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
とサービス ワーカーの間で通信することは可能です。workbox-window
を使用すると、workbox-window
モジュールの messageSW
メソッドを使用して、2 つのスコープ間の通信を簡単に行うことができます。
Workbox はメッセージに特定の形式を使用します。次のプロパティを持つオブジェクトです。
type
は、メッセージを一意に識別する必須の文字列です。形式は、単語をアンダースコアで区切った大文字にする必要があります(例:CACHE_URLS
)。meta
は、メッセージの送信に使用するワークボックス パッケージの名前を表すオプションの文字列で、通常は省略されます。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 のアップデートが利用可能になったらユーザーに通知するなど、Service Worker と window
間の通信はさまざまな場面で役に立ちます。このレシピは、messageSkipWaiting
という self.skipWaiting
の特別なヘルパー メソッドを利用しています。このメソッドは、type
の値が SKIP_WAITING
のメッセージを送信します。