サービス ワーカーと Cache Storage API を使用するデベロッパーは、Chrome 71 で展開される 2 つの小さな変更に注意する必要があります。どちらの変更も、Chrome の実装を仕様と他のブラウザに近づけるものです。
非同期 importScripts() の禁止
importScripts()
は、メインの Service Worker スクリプトに、現在の実行を一時停止し、指定された URL から追加のコードをダウンロードして、現在のグローバル スコープで完了まで実行するよう指示します。完了すると、メイン サービス ワーカー スクリプトの実行が再開されます。importScripts()
は、組織上の理由でメインのサービス ワーカー スクリプトを小さな部分に分割する場合や、サードパーティ コードをプルしてサービス ワーカーに機能を追加する場合に便利です。
ブラウザは、importScripts()
を介して pull されたものを自動的にキャッシュに保存することで、「同期コードをダウンロードして実行する」というパフォーマンスの問題を軽減しようとします。つまり、最初のダウンロード後、インポートされたコードの実行に伴うオーバーヘッドはほとんどありません。
ただし、この機能が機能するには、最初のインストール後に Service Worker に「予期しない」コードがインポートされないことをブラウザが認識する必要があります。Service Worker の仕様では、importScripts()
の呼び出しは、トップレベルの Service Worker スクリプトの同期実行中、または必要に応じて install
ハンドラ内で非同期にのみ機能することが想定されています。
Chrome 71 より前は、install
ハンドラの外部で importScripts()
を非同期で呼び出すと機能していました。Chrome 71 以降では、これらの呼び出しは、他のブラウザの動作と一致して、(同じ URL が install
ハンドラで以前にインポートされていない限り)ランタイム例外をスローします。
次のようなコードではなく、
// This only works in Chrome 70 and below.
self.addEventListener('fetch', event => {
importScripts('my-fetch-logic.js');
event.respondWith(self.customFetchLogic(event));
});
サービス ワーカーのコードは次のようになります。
// Move the importScripts() to the top-level scope.
// (Alternatively, import the same URL in the install handler.)
importScripts('my-fetch-logic.js');
self.addEventListener('fetch', event => {
event.respondWith(self.customFetchLogic(event));
});
cache.addAll() に渡される重複する URL の非推奨
Cache Storage API をサービス ワーカーとともに使用している場合、Chrome 71 では関連する仕様に合わせて、別の小さな変更も行われています。同じ URL が 1 回の cache.addAll()
呼び出しに複数回渡された場合、呼び出しから返された Promise は拒否される必要があります。
Chrome 71 より前は、この問題は検出されず、重複する URL は事実上無視されていました。
このロギングは Chrome 72 の前兆です。Chrome 72 では、重複する URL がロギングされた警告ではなく、cache.addAll()
の拒否につながります。一般的な方法として、InstallEvent.waitUntil()
に渡される Promise チェーンの一部として cache.addAll()
を呼び出す場合、この拒否により Service Worker のインストールに失敗する可能性があります。
次のような問題が発生する可能性があります。
const urlsToCache = [
'/index.html',
'/main.css',
'/app.js',
'/index.html', // Oops! This is listed twice and should be removed.
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open('my-cache').then(cache => cache.addAll(urlsToCache))
);
});
この制限は、cache.addAll()
に渡される実際の URL にのみ適用されます。最終的に URL が異なる 2 つの同等のレスポンス('/'
と '/index.html'
など)をキャッシュに保存しても、拒否はトリガーされません。
Service Worker の実装を幅広くテストする
現時点では、Service Worker はすべての主要な「エバーグリーン」ブラウザで広く実装されています。多数のブラウザでプログレッシブ ウェブアプリを定期的にテストしている場合や、Chrome を使用していないユーザーが多数いる場合は、すでに不一致を検出してコードを更新している可能性があります。ただし、他のブラウザでこの動作に気付いていない可能性もあるため、Chrome の動作を変更する前に、この変更についてお知らせいたします。