workbox-window
パッケージは、Python や SDK での実行を想定したモジュールのセットです。
window
コンテキスト:
ウェブページ内に表示されます他のワークボックスを補完するものである
パッケージもサポートしています。
workbox-window
の主な機能/目標は次のとおりです。
- Service Worker の登録と更新のプロセスを簡略化するために、 Service Worker のライフサイクルにおける最も重要な瞬間をデベロッパーが特定し、 その瞬間に反応できます
- デベロッパーがよくあるミスを犯しないようにするため。
- より簡単なコミュニケーションを実現するため ウィンドウで実行中のコードと Service Worker で実行中のコードの間で
Workbox-window のインポートと使用
workbox-window
パッケージの主なエントリ ポイントは Workbox
クラスです。
Google の CDN からコードにインポートすることも、一般的な
JavaScript バンドルツール。
CDN を使用する
サイトに Workbox
クラスをインポートする最も簡単な方法は、CDN を使用する方法です。
<script type="module">
import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-window.prod.mjs';
if ('serviceWorker' in navigator) {
const wb = new Workbox('/sw.js');
wb.register();
}
</script>
この例では、<script type="module">
と import
ステートメントを使用して、
Workbox
クラスを読み込みます。これをトランスパイルする必要があると思われるかもしれませんが、
古いブラウザで動作させることができますが、実際にはその必要はありません。
Service Worker をサポートするすべての主要なブラウザは、ネイティブ JavaScript モジュールもサポートしているため、 どのブラウザにもこのコードを提供しても問題はありません(古いブラウザでは無視されます)。
JavaScript バンドラを使用した Workbox の読み込み
workbox-window
を使用するのにツールは必要ありませんが、
開発インフラストラクチャには、次のようなバンドラがすでに含まれています。
機能する webpack または Rollup
npm 依存関係がある場合、それらを使用して
workbox-window
を読み込みます。
最初のステップは
インストール
workbox-window
をアプリケーションの依存関係として使用します。
npm install workbox-window
次に、アプリケーションの JavaScript ファイルの 1 つに、import
ワークボックスを
workbox-window
パッケージ名を参照します。
import {Workbox} from 'workbox-window';
if ('serviceWorker' in navigator) {
const wb = new Workbox('/sw.js');
wb.register();
}
バンドラが動的インポート ステートメントによるコード分割をサポートしている場合は、
また、条件付きで workbox-window
を読み込むこともできます。これにより、
メインバンドルのサイズを指定します
workbox-window
は非常に小さいが、その理由は明らかではない。
サイトのコアアプリロジックとともに
読み込む必要があります
その性質上、漸進的な機能強化です。
if ('serviceWorker' in navigator) {
const {Workbox} = await import('workbox-window');
const wb = new Workbox('/sw.js');
wb.register();
}
高度なバンドルのコンセプト
Service Worker で実行される Workbox パッケージとは異なり、ビルドファイルは
workbox-window
が参照
main
および
次の module
フィールド:
package.json
は ES5 にトランスパイルされます。そのため
その一部では、デベロッパーがさまざまなビルドツールを
node_module
依存関係。
ビルドシステムで依存関係のトランスパイルが許可されている場合(または コードをトランスパイルする必要がない場合)は、 ソースファイルに 直接アクセスします
Workbox
をインポートするさまざまな方法と、以下で説明します。
それぞれが返す結果は次のようになります。
// Imports a UMD version with ES5 syntax
// (pkg.main: "build/workbox-window.prod.umd.js")
const {Workbox} = require('workbox-window');
// Imports the module version with ES5 syntax
// (pkg.module: "build/workbox-window.prod.es5.mjs")
import {Workbox} from 'workbox-window';
// Imports the module source file with ES2015+ syntax
import {Workbox} from 'workbox-window/Workbox.mjs';
例
Workbox
クラスをインポートしたら、それを使用して登録と
Service Worker と通信します。この例は、
Workbox
:
Service Worker を登録し、Service Worker が初めてアクティブになったときにユーザーに通知する
多くのウェブ アプリケーションでは、アプリが機能するように Service Worker でアセットを事前キャッシュに保存 後続のページ読み込み時にオフラインになります情報によっては、 アプリがオフラインで利用可能になったことをユーザーに知らせます。
const wb = new Workbox('/sw.js');
wb.addEventListener('activated', event => {
// `event.isUpdate` will be true if another version of the service
// worker was controlling the page when this version was registered.
if (!event.isUpdate) {
console.log('Service worker activated for the first time!');
// If your service worker is configured to precache assets, those
// assets should all be available now.
}
});
// Register the service worker after event listeners have been added.
wb.register();
Service Worker をインストールしたが、有効化の待機状態から先に進まない場合にユーザーに通知する
既存の Service Worker によって制御されているページが新しいサービスを登録したとき デフォルトでは、Service Worker はすべてのクライアントが 完全にアンロードされます。
これが開発者を混乱させる一般的な原因です。特に、 現在のページを再読み込みしても、新しい Service Worker はアクティブになりません。
混乱を最小限に抑え、状況を明確にするために、
Workbox
クラスには、リッスンできる waiting
イベントが用意されています。
const wb = new Workbox('/sw.js');
wb.addEventListener('waiting', event => {
console.log(
`A new service worker has installed, but it can't activate` +
`until all tabs running the current version have fully unloaded.`
);
});
// Register the service worker after event listeners have been added.
wb.register();
workbox-broadcast-update
パッケージからのキャッシュ更新についてユーザーに通知する
workbox-broadcast-update
パッケージは、キャッシュからコンテンツを配信(高速配信)できる優れた方法です。また、
ユーザーにそのコンテンツの更新情報を通知することができます(
stale-while-revalidate 戦略)。
このウィンドウからこれらの最新情報を受け取るには、次の message
イベントをリッスンします。
タイプ CACHE_UPDATED
:
const wb = new Workbox('/sw.js');
wb.addEventListener('message', event => {
if (event.data.type === 'CACHE_UPDATED') {
const {updatedURL} = event.data.payload;
console.log(`A newer version of ${updatedURL} is available!`);
}
});
// Register the service worker after event listeners have been added.
wb.register();
キャッシュに保存する URL のリストを Service Worker に送信する
アプリケーションによっては、作成する必要のあるアセットをすべて把握し、 完全に異なるページを提供するアプリケーションもあれば、 ユーザーが最初にアクセスした URL に基づいて 自動的に配信されます
後者のカテゴリのアプリの場合、アセットのみをキャッシュに保存するのが理にかなっています。
ユーザーがアクセスした特定のページに必要な
アクションを確認できます
workbox-routing
パッケージでは、
ルーターにキャッシュする URL のリストを送信すると、キャッシュに
ルールが適用されます。
この例では、URL が読み込まれるたびに、ページで読み込まれた URL のリストがルーターに 有効になります。なお、すべての URL を送信しても、 Service Worker で定義されたルートに一致する URL がキャッシュに保存されます。
const wb = new Workbox('/sw.js');
wb.addEventListener('activated', event => {
// Get the current page URL + all resources the page loaded.
const urlsToCache = [
location.href,
...performance.getEntriesByType('resource').map(r => r.name),
];
// Send that list of URLs to your router in the service worker.
wb.messageSW({
type: 'CACHE_URLS',
payload: {urlsToCache},
});
});
// Register the service worker after event listeners have been added.
wb.register();
Service Worker のライフサイクルに関する重要な瞬間
Service Worker のライフサイクル 複雑で、完全に理解するのは難しい場合があります。その理由の 1 つは、 非常に複雑です あらゆる用途ですべてのエッジケースを処理 Service Worker(複数の Service Worker の登録、 異なるフレームでの異なる Service Worker の登録、 異なる名前など)が使用されます。
ただし、Service Worker を実装するほとんどのデベロッパーは、 使用が非常に簡単です。ほとんどのデベロッパー ページの読み込みごとに 1 つの Service Worker しか登録されず、Service Worker の名前は変更されない サーバーにデプロイされます。
Workbox
クラスは、Service Worker のライフサイクルに関するこのシンプルなビューを活用しています。
すべての Service Worker 登録を 2 つのカテゴリ(インスタンスの
登録済みの Service Worker と外部 Service Worker の 2 つの種類があります。
- 登録済みの Service Worker: インストールを開始した Service Worker
Workbox
インスタンスがregister()
を呼び出した結果、またはすでにアクティブな Service Worker(register()
の呼び出しによって登録時にupdatefound
イベントがトリガーされなかった場合) - 外部 Service Worker: インストールを開始した Service Worker
register()
を呼び出すWorkbox
インスタンスとは独立して動作します。これは通常 ユーザーがサイトの新しいバージョンを別のタブで開いたときに発生します。特定の 外部の Service Worker から発生した場合、イベントのisExternal
プロパティがtrue
に設定されます。
この 2 種類の Service Worker を念頭に置きながら、 Service Worker のライフサイクルにおける重要な瞬間を、デベロッパー向けの推奨事項とともにご紹介します。 をご覧ください。
Service Worker を初めてインストールするときは、
Service Worker を初めてインストールするときは 処理方法が異なります
workbox-window
では、最初にバージョンを区別できます。
インストールおよび今後の更新について、[isUpdate
] プロパティを
トリガーされます。最初のインストールでは、isUpdate
は次のようになります。
false
。
const wb = new Workbox('/sw.js');
wb.addEventListener('installed', event => {
if (!event.isUpdate) {
// First-installed code goes here...
}
});
wb.register();
Service Worker の更新バージョンが見つかった場合
新しい Service Worker がインストールを開始したものの、その時点で既存のバージョンがインストールされ、
ページを制御する場合、以下のすべてのイベントの isUpdate
プロパティが
true
にします。
この状況でどのように対応するかは、一般的に最初の ユーザーがこのアップデートを入手するタイミングと方法を管理する必要があるからです。
想定外のバージョンの Service Worker が見つかった場合
ユーザーがサイトをバックグラウンドのタブで長時間開いたままにすることがあります あります。知らないうちに新しいタブを開いてサイトにアクセスすることもあり バックグラウンドタブでサイトがすでに開かれていますこのような場合は、 2 つのバージョンのサイトを同時に実行し 開発者にとって興味深い問題がいくつか提示されます
たとえば、タブ A でサイトの v1 を実行し、タブ B がある場合を考えてみます 実行しています。タブ B が読み込まれると、サービスのバージョンによって制御されます v1 で出荷されたものの、サーバーから返されるページは ネットワークファースト キャッシュ戦略 にすべての v2 アセットが含まれます。
しかしタブ B では一般的に問題になりません。なぜなら、v2 の v1 コードの仕組みを知っていました。ただし、 問題になります。これは、v1 のコードでは、 おすすめします。
このような状況に対処するために、workbox-window
はライフサイクルのディスパッチも行います。
リモート エージェントが「外部」からの更新を検出すると、Service Worker です。ここで、
外部とは単に、現在の Workbox
のバージョン以外の任意のバージョンを意味します。
登録されます。
Workbox v6 以降では、これらのイベントは、
各イベントに isExternal: true
プロパティを追加しています。
渡されます。ウェブ アプリケーションに特定のロジックを実装して、
「外部」そのプロパティをイベント ハンドラで確認できます。
よくあるミスを回避する
Workbox が提供する最も便利な機能の一つは、デベロッパー ロギングです。そして
これは workbox-window
に特に当てはまります。
Service Worker での開発はわかりにくい場合が多く 予想に反する結果になった場合、原因を特定するのは難しい場合があります。
たとえば、Service Worker に変更を加えてページを再読み込みすると、 ブラウザではその変更が反映されない場合があります。最も可能性の高い理由は Service Worker がまだ有効化を待機している状態です。
ただし、Workbox
クラスに Service Worker を登録すると、
ライフサイクル状態のすべての変更について通知を受け取れます。
期待どおりに動作しない理由をデバッグするのに役立ちます。
また、Service Worker を初めて使用するときにデベロッパーが犯しがちなミスは、 Service Worker を登録するには、 間違ったスコープです。
これを防ぐために、Workbox
クラスは、次の場合に警告を発します。
Service Worker を登録するページは、その Service Worker のスコープ外です。また、
Service Worker はアクティブになっているものの、まだ
ページを制御する方法は次のようになります。
Service Worker へのウィンドウ通信
Service Worker の高度な使用方法では、
ウィンドウが表示されます。Workbox
クラスを使用すると、次のこともできます。
messageSW()
メソッドを提供しpostMessage()
Service Worker を登録し、レスポンスを待ちます。
Service Worker にはどの形式でもデータを送信できますが、 3 つのプロパティ(後者の 2 つは 省略可):
messageSW()
メソッド経由で送信されるメッセージでは MessageChannel
が使用されるため、レシーバは
対応できます。メッセージに返信するには、
メッセージ イベント リスナー内の event.ports[0].postMessage(response)
。「
messageSW()
メソッドは、あらゆる response
に解決される Promise を返します。
表示されます。
次に、ウィンドウから Service Worker にメッセージを送信し、
応答があります。最初のコードブロックは、
2 番目のブロックでは、Workbox
クラスを使用して、
レスポンスを待ちます。
sw.js のコード:
const SW_VERSION = '1.0.0';
addEventListener('message', event => {
if (event.data.type === 'GET_VERSION') {
event.ports[0].postMessage(SW_VERSION);
}
});
main.js のコード(ウィンドウ内で実行):
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 の間でやり取りされる 注意すべき点は、Service Worker で同じバージョンの Pod を その問題に対処するためのソリューションについて 説明します 問題は、ページをネットワーク ファーストで配信しているか、 (キャッシュファースト)
ネットワーク ファースト
ページのネットワークを最初に配信する場合、ユーザーには常に 最新バージョンの HTML をサーバーからダウンロードします。ただし、初めてユーザーが (アップデートをデプロイした後に)サイトに再度アクセスすると、HTML が 最新バージョンですが、ブラウザで実行されている Service Worker は 以前にインストールしたバージョン(多くのバージョンが古い可能性があります)。
この可能性を理解することが重要です。JavaScript が 送信すると、そのページの古いバージョンに そのバージョンでは、どのように応答すべきかわからない(または 互換性のない形式など)。
そのため、常に Service Worker をバージョニングし、 重要な作業を行う前に、互換性のあるバージョンを確認してください。
たとえば、上記のコードでは、返された Service Worker のバージョンが
messageSW()
の呼び出しが想定したバージョンよりも古いため、待機することをおすすめします
更新が検出されるまで待機します(register()
を呼び出した場合に行われます)。ちなみに
ユーザーまたは更新を通知することも、手動で
待機フェーズをスキップ
新しい Service Worker をすぐに有効にできます。
キャッシュ ファースト
ページを最初に配信する場合は
ネットワークファーストではなく
まずページの最初のバージョンは常に
(そのサービスによってサービスが提供されるため)。その結果
messageSW()
をすぐに使用できます。
ただし、新しいバージョンの Service Worker が見つかり、
ページで register()
が呼び出されたとき(つまり、意図的に待機フェーズをスキップしている)場合、
安全にメッセージを送信できなくなる可能性があります。
この可能性を管理する戦略の一つは、バージョン管理スキームを 互換性を損なう更新と互換性を損なわない更新を区別でき、 互換性を破る更新の場合は 使用します。代わりに、古いバージョンを実行していることをユーザーに ページのバージョンを確認し、更新を適用するために再読み込みすることを提案します。
待機ヘルパーをスキップ
Window to Service Worker メッセージの一般的な使用規則は、
インストールされている Service Worker に指示する {type: 'SKIP_WAITING'}
メッセージ
待機フェーズをスキップ
有効にします。
Workbox v6 以降では、messageSkipWaiting()
メソッドを使用して、
「{type: 'SKIP_WAITING'}
」というメッセージを、関連付けられた
現在の Service Worker 登録情報。音声通知がない場合は、何も通知せずに
待機しています。
型
Workbox
Service Worker の登録、更新、 Service Worker のライフサイクル イベントに反応します。
プロパティ
-
コンストラクタ
void
スクリプト URL と Service Worker を使用して新しい Workbox インスタンスを作成する 。スクリプトの URL とオプションは、スクリプトの URL とオプションの navigator.serviceWorker.register(scriptURL, options) を呼び出す。
constructor
関数は次のようになります。(scriptURL: string | TrustedScriptURL, registerOptions?: object) => {...}
-
scriptURL
string |TrustedScriptURL
Service Worker スクリプト 関連付けられています使用
TrustedScriptURL
はサポートされています。 -
registerOptions
オブジェクト(省略可)
-
戻り値
-
-
アクティブ
Promise<ServiceWorker>
-
コントロール
Promise<ServiceWorker>
-
getSW
void
スクリプト URL と一致する Service Worker への参照で解決します 新しいインスタンスが作成されます
登録時に、すでに有効なサービスまたは待機中のサービスがある場合 スクリプト URL が一致する場合は、そのスクリプトが使用されます( アクティブな Service Worker よりも Service Worker が優先される 一致するため、待機中の Service Worker が 。 登録時に一致するアクティブまたは待機中の Service Worker がない場合 更新が検出されて開始されるまで、Promise は解決されません。 その時点で、インストール用の Service Worker が使用されます。
getSW
関数は次のようになります。() => {...}
-
戻り値
Promise<ServiceWorker>
-
-
messageSW
void
渡されたデータ オブジェクトを、このメソッドで登録された Service Worker に送信します。 インスタンス(
workbox-window.Workbox#getSW
経由)と レスポンス(ある場合)を返信します。Service Worker のメッセージ ハンドラでレスポンスを設定するには、
event.ports[0].postMessage(...)
を呼び出すと、Promise が解決されます。messageSW()
から返されます。レスポンスが設定されていない場合、Promise は 解決しますmessageSW
関数は次のようになります。(data: object) => {...}
-
データ
オブジェクト
Service Worker に送信するオブジェクト
-
戻り値
<任意> を約束する
-
-
messageSkipWaiting
void
Service Worker に
{type: 'SKIP_WAITING'}
メッセージを送信し、 現在、現在の登録に関連付けられたwaiting
状態になっています。現在の登録がない場合や、Service Worker が
waiting
でない場合、 これを呼び出しても効果はありません。messageSkipWaiting
関数は次のようになります。() => {...}
-
register
void
このインスタンス スクリプトの URL とサービスの Service Worker を登録します。 選択できます。デフォルトでは、このメソッドは登録を ウィンドウが読み込まれました。
register
関数は次のようになります。(options?: object) => {...}
-
オプション
オブジェクト(省略可)
-
即時
ブール値(省略可)
-
-
戻り値
Promise<ServiceWorkerRegistration>
-
-
update
void
登録済みの Service Worker のアップデートを確認します。
update
関数は次のようになります。() => {...}
-
戻り値
約束 <void>
-
WorkboxEventMap
プロパティ
-
コントロール
-
インストール済み
-
installing
-
メッセージ
WorkboxLifecycleEvent
プロパティ
-
isExternal
ブール値(省略可)
-
isUpdate
ブール値(省略可)
-
originalEvent
イベント(省略可)
-
sw
Service Worker(省略可)
-
ターゲット
WorkboxEventTarget(省略可)
-
type
typeOperator
WorkboxLifecycleEventMap
プロパティ
-
コントロール
-
インストール済み
-
installing
WorkboxLifecycleWaitingEvent
プロパティ
-
isExternal
ブール値(省略可)
-
isUpdate
ブール値(省略可)
-
originalEvent
イベント(省略可)
-
sw
Service Worker(省略可)
-
ターゲット
WorkboxEventTarget(省略可)
-
type
typeOperator
-
wasWaitingBeforeRegister
ブール値(省略可)
WorkboxMessageEvent
プロパティ
-
データ
任意
-
isExternal
ブール値(省略可)
-
originalEvent
イベント
-
ports
typeOperator
-
sw
Service Worker(省略可)
-
ターゲット
WorkboxEventTarget(省略可)
-
type
"メッセージ"
メソッド
messageSW()
workbox-window.messageSW(
sw: ServiceWorker,
data: object,
)
postMessage
を介して Service Worker にデータ オブジェクトを送信し、
レスポンス(存在する場合)を返します。
Service Worker のメッセージ ハンドラでレスポンスを設定するには、
event.ports[0].postMessage(...)
を呼び出すと、Promise が解決されます。
messageSW()
から返されます。レスポンスが設定されていない場合、Promise は
解決します
パラメータ
-
sw
ServiceWorker
メッセージの送信先の Service Worker。
-
データ
オブジェクト
Service Worker に送信するオブジェクト。
戻り値
-
<任意> を約束する