Workbox v2 から v3 に移行する

このガイドでは、Workbox v3 で導入された互換性を破る変更を中心に、Workbox v2 の設定からアップグレードする際に行う必要がある変更の例を交えて説明します。

従来の sw-precachesw-toolbox の組み合わせを現在ご利用で、初めて Workbox に移行する場合は、別の移行ガイドをご参照ください。

V3 の背景

Workbox の v3 リリースは、既存のコードベースを大幅にリファクタリングするものです。全体的な目標は次のとおりです。

  • ワークボックスのサイズを最小限に抑える。ダウンロードおよび実行される Service Worker のランタイム コードの量が削減されました。全員をモノリシック バンドルにオプトインするのではなく、使用している特定の機能のコードのみがランタイムにインポートされます。
  • Workbox には CDN があります。Google は、Workbox ランタイム ライブラリにアクセスするための正規オプションとして、完全にサポートされている Google Cloud Storage ベースの CDN ホスティングを提供しています。これにより、Workbox を簡単に起動して実行できます。
  • デバッグとログの改善。デバッグとロギングのエクスペリエンスが大幅に改善されました。Workbox が localhost オリジンから使用され、すべてのロギングとアサーションが本番環境ビルドから削除されると、常にデバッグログがデフォルトで有効になります。 Workbox v3 に用意されているデバッグ ロギングの例。
  • webpack プラグインの改善workbox-webpack-plugin は webpack のビルドプロセスと緊密に統合されているため、ビルド パイプライン内のすべてのアセットを事前キャッシュする場合、構成なしでユースケースに対応できます。

これらの目標を達成し、使いにくいと感じたりアンチパターンの原因になったりする以前のインターフェースの一部の側面を一掃するには、v3 リリースに多くの破壊的変更を導入する必要がありました。

互換性を損なう変更

ビルド構成

以下の変更は、構成オプションのセットを共有しているすべてのビルドツール(workbox-buildworkbox-cliworkbox-webpack-plugin)の動作に影響します。

  • 以前は 'fastest' ハンドラ名は有効で、runtimeCaching の構成時に 'staleWhileRevalidate' のエイリアスとして扱われていました。現在は無効になっているため、デベロッパーは直接 'staleWhileRevalidate' を使用するように切り替える必要があります。
  • いくつかの runtimeCaching.options プロパティ名が更新され、追加のパラメータ検証も実施されています。検証は、無効な構成を使用した場合にビルドが失敗する原因となります。現在サポートされているオプションの一覧については、runtimeCachingドキュメントをご覧ください。

ワークボックス-背景-同期

  • maxRetentionTime 設定パラメータが、ミリ秒数ではなく分数として解釈されるようになりました。
  • キュー名を表す必須の文字列が追加されました。これは、プラグインまたはスタンドアロンのクラスを作成するときに最初のパラメータとして渡す必要があります。(以前、これはオプションのプロパティとして渡されました)。更新された API サーフェスについては、ドキュメントをご覧ください。

workbox-broadcast-cache-update

  • チャンネル名を表す必須の文字列が追加されました。これは、プラグインまたはスタンドアロンのクラスを作成するときに最初のパラメータとして渡す必要があります。

たとえば、v2 では Plugin クラスを次のように初期化します。

new workbox.broadcastCacheUpdate.BroadcastCacheUpdatePlugin({
  channelName: 'cache-updates',
  headersToCheck: ['etag'],
});

v3 での同等の使用方法は次のとおりです。

new workbox.broadcastUpdate.Plugin('cache-updates', {headersToCheck: ['etag']});

更新された API サーフェスについては、ドキュメントをご覧ください。

ワークボックスのビルド

  • デフォルトでは、glob パターン マッチングがオプションfollow: true(シンボリック リンクに従う)と strict: true(異常なエラーに対する耐性が低い)を使用して実行されるようになりました。ビルド構成で globFollow: false または globStrict: false を設定すると、どちらかを無効にして以前の動作に戻すことができます。
  • workbox-build のすべての関数は、返されるレスポンスで追加のプロパティ warnings を返します。v2 で致命的なエラーとして扱われていたシナリオの一部が許可されましたが、warnings(文字列の配列)を介してレポートされます。

v2 では、次のように generateSW を呼び出すことができます。

const workboxBuild = require('workbox-build');

workboxBuild.generateSW({...})
  .then(({count, size}) => console.log(`Precached ${count} files, totaling ${size} bytes.`))
  .catch((error) => console.error(`Something went wrong: ${error}`));

v3 でも同じコードを使用できますが、warnings を確認してログに記録することをおすすめします。

const workboxBuild = require('workbox-build');

workboxBuild.generateSW({...})
  .then(({count, size, warnings}) => {
    for (const warning of warnings) {
      console.warn(warning);
    }
    console.log(`Precached ${count} files, totalling ${size} bytes.`);
  })
  .catch((error) => console.error(`Something went wrong: ${error}`));
  • v2 で独自のカスタム ManifestTransform 関数を記述したデベロッパーは、オブジェクト内でマニフェスト配列を返す必要があります(return manifestArray; ではなく return {manifest: manifestArray}; を使用する必要があります)。これにより、プラグインにオプションの warnings プロパティを含めることができます。これは、致命的でない警告情報を含む文字列の配列です。

v2 でカスタム ManifestTransform を記述している場合は、コードは次のようになります。

const cdnTransform = manifestEntries => {
  return manifestEntries.map(entry => {
    const cdnOrigin = 'https://example.com';
    if (entry.url.startsWith('/assets/')) {
      entry.url = cdnOrigin + entry.url;
    }
    return entry;
  });
};

v3 は次のバージョンと同等です。

const cdnTransform = manifestEntries => {
  const manifest = manifestEntries.map(entry => {
    const cdnOrigin = 'https://example.com';
    if (entry.url.startsWith('/assets/')) {
      entry.url = cdnOrigin + entry.url;
    }
    return entry;
  });
  return {manifest, warnings: []};
};
  • getFileManifestEntries() 関数の名前が getManifest() に変更され、返される Promise に、事前キャッシュに保存された URL に関する追加情報が含まれるようになりました。

v2 では次のようなコードになります。

const manifestEntries = await workboxBuild.getFileManifestEntries({...});

これは v3 で次のように書き換えることができます。

const {manifestEntries, count, size, warnings} = await workboxBuild.getManifest({...});

// Use manifestEntries like before.
// Optionally, log the new info returned in count, size, warnings.
  • generateFileManifest() 関数を削除しました。代わりに getManifest() を呼び出し、そのレスポンスを使用して適切な形式でディスクにデータを書き込むことをおすすめします。

ワークボックスのキャッシュの有効期限

  • プラグイン API に変更はありません。ほとんどのデベロッパーが使用するモードです。ただし、API をスタンドアロン クラスとして使用するデベロッパーに影響する重大な変更があります。更新された API サーフェスについては、ドキュメントをご覧ください。

workbox-cli

デベロッパーは、--help フラグを使用して CLI を実行すると、サポートされているすべてのパラメータを確認できます。

  • バイナリ スクリプトの workbox-cli エイリアスはサポートされなくなりました。これで、バイナリには workbox としてのみアクセスできるようになりました。
  • v3 では、v2 コマンド generate:swinject:manifest の名前が generateSWinjectManifest に変更されました。
  • v2 では、デフォルト構成ファイル(明示的に指定されていない場合に使用される)は、現在のディレクトリの workbox-cli-config.js であると想定されていました。v3 では workbox-config.js です。

つまり、v2 では以下のようになります。

$ workbox inject:manifest

この場合、workbox-cli-config.js と v3 から読み取られた構成を使用して、「マニフェストを挿入」のビルドプロセスを実行します。

$ workbox injectManifest

同じ処理を行いますが、workbox-config.js から構成を読み取ります。

ワークボックスのプレキャッシュ

  • 以前は precache() メソッドは、キャッシュの変更を行い、キャッシュに保存されたエントリを提供するようにルーティングを設定していました。現在、precache() はキャッシュ エントリのみを変更するほか、キャッシュに保存されたレスポンスを提供するルートを登録するための新しいメソッド addRoute() を公開しました。以前の 2-in-1 機能を必要とするデベロッパーは、precacheAndRoute() の呼び出しに切り替えることができます。
  • WorkboxSW コンストラクタを介して設定されていたいくつかのオプションが、workbox.precaching.precacheAndRoute([...], options)options パラメータとして渡されるようになりました。これらのオプションが設定されていない場合のデフォルトについては、リファレンス ドキュメントをご覧ください。
  • デフォルトでは、ファイル拡張子のない URL について、.html 拡張子を含むキャッシュ エントリとの一致が自動的にチェックされます。たとえば、(事前キャッシュされていない)/path/to/index のリクエストが行われ、/path/to/index.html に事前キャッシュに保存されたエントリがある場合は、その事前キャッシュに保存されたエントリが使用されます。デベロッパーは、オプションを workbox.precaching.precacheAndRoute() に渡すときに {cleanUrls: false} を設定することで、この新しい動作を無効にできます。
  • 事前キャッシュに保存されたアセットのキャッシュの更新を通知するように workbox-broadcast-update が自動的に設定されなくなります。

v2 のコードは次のようになります。

const workboxSW = new self.WorkboxSW({
  directoryIndex: 'index.html',
  ignoreUrlParametersMatching: [/^utm_/],
  precacheChannelName: 'precache-updates',
});
workboxSW.precache([...]);

v3 は次のバージョンと同等です。

workbox.precaching.addPlugins([
    new workbox.broadcastUpdate.Plugin('precache-updates')
]);

workbox.precaching.precacheAndRoute([...], {
  cleanUrls: false,
  directoryIndex: 'index.html',
  ignoreUrlParametersMatching: [/^utm_/],
});

ワークボックス ルーティング

  • 以前に WorkboxSW オブジェクトの workbox.router.* 名前空間を介して workbox-routing を使用していたデベロッパーは、新しい名前空間 workbox.routing.* に切り替える必要があります。
  • ルートは、最初に登録された順に評価されるようになりました。これは、v2 で使用された Route の評価とは逆の順序で、最後に登録された Route が優先されます。
  • ExpressRoute クラスと、「Express スタイル」のワイルドカードのサポートが削除されました。これにより、workbox-routing のサイズが大幅に削減されます。workbox.routing.registerRoute() の最初のパラメータとして使用される文字列が完全一致として扱われるようになりました。ワイルドカードまたは部分一致は、RegExp で処理する必要があります。リクエスト URL の一部または全部に一致する RegExp を使用すると、ルートをトリガーできます。
  • Router クラスの addFetchListener() ヘルパー メソッドが削除されました。デベロッパーは、独自の fetch ハンドラを明示的に追加することも、workbox.routing が提供するインターフェースを使用して、独自の fetch ハンドラを暗黙的に作成することもできます。
  • registerRoutes() メソッドと unregisterRoutes() メソッドが削除されました。1 つの Route で動作するこれらのメソッドのバージョンは変更されていません。複数のルートを一度に登録または登録解除する必要があるデベロッパーは、代わりに registerRoute() または unregisterRoute() を連続して呼び出す必要があります。

v2 のコードは次のようになります。

const workboxSW = new self.WorkboxSW();

workboxSW.router.registerRoute(
  '/path/with/.*/wildcard/',
  workboxSW.strategies.staleWhileRevalidate()
);

workboxSW.router.registerRoute(
  new RegExp('^https://example.com/'),
  workboxSW.strategies.networkFirst()
);

v3 は次のバージョンと同等です。

workbox.routing.registerRoute(
  new RegExp('^https://example.com/'),
  workbox.strategies.networkFirst()
);

workbox.routing.registerRoute(
  new RegExp('^/path/with/.*/wildcard'),
  workbox.strategies.staleWhileRevalidate()
);

workbox-strategies(以前の workbox-runtime-caching)

  • workbox-runtime-caching モジュールは正式に workbox-strategies として知られ、新しい名前で npm に公開されました。
  • 戦略でキャッシュ名を指定せずにキャッシュの有効期限を使用すると、無効になります。v2 では可能でした。
workboxSW.strategies.staleWhileRevalidate({
  cacheExpiration: {maxEntries: 50},
});

そうすると、デフォルト キャッシュに有効期限付きのエントリが追加されることになりますが、これは想定外です。v3 では、キャッシュ名は必須です。

workboxSW.strategies.staleWhileRevalidate({
  cacheName: 'my-cache',
  plugins: [new workbox.expiration.Plugin({maxEntries: 50})],
});
  • cacheWillMatch ライフサイクル メソッドの名前が cachedResponseWillBeUsed に変更されました。cacheWillMatch に反応する独自のプラグインを作成していない限り、これは目に見える変化ではないはずです。
  • 戦略を構成する際にプラグインを指定する構文が変更されました。戦略設定の plugins プロパティで、各プラグインを明示的にリストする必要があります。

v2 のコードは次のようになります。

const workboxSW = new self.WorkboxSW();

const networkFirstStrategy = workboxSW.strategies.networkFirst({
  cacheName: 'my-cache',
  networkTimeoutSeconds: 5,
  cacheExpiration: {
    maxEntries: 50,
  },
  cacheableResponse: {
    statuses: [0, 200],
  },
});

v3 は次のバージョンと同等です。

const networkFirstStrategy = workbox.strategies.networkFirst({
  cacheName: 'my-cache',
  networkTimeoutSeconds: 5,
  plugins: [
    new workbox.expiration.Plugin({maxEntries: 50}),
    new workbox.cacheableResponse.Plugin({statuses: [0, 200]}),
  ],
});

詳しくは、プラグインの使用ガイドをご覧ください。

ワークボックス スイッチ

  • 内部的には、workbox-sw が軽量の「ローダー」インターフェースに書き換えられています。このインターフェースは、いくつかの基本構成を必要とし、実行時に必要な他のモジュールを取り込む役割を担います。デベロッパーは、WorkboxSW クラスの新しいインスタンスを作成する代わりに、グローバル名前空間に自動的に公開される既存のインスタンスを操作します。

以前のバージョン 2:

importScripts('<path to workbox-sw>/importScripts/workbox-sw.prod.v2.1.3.js');

const workbox = new WorkboxSW({
  skipWaiting: true,
  clientsClaim: true,
  // etc.
});

workbox.router.registerRoute(...);

v3 では、workbox-sw.js スクリプトをインポートするだけで、すぐに使用できるインスタンスが workbox としてグローバル名前空間で自動的に利用可能になります。

importScripts('<path to workbox-sw>/3.0.0/workbox-sw.js');

// workbox is implicitly created and ready for use.
workbox.routing.registerRoute(...);
  • skipWaitingclientsClaim は、WorkboxSW コンストラクタに渡されるオプションではなくなりました。代わりに、メソッド workbox.clientsClaim()workbox.skipWaiting() に変更されました。
  • v2 コンストラクタで以前サポートされていた handleFetch オプションは、v3 ではサポートされなくなりました。フェッチ ハンドラを呼び出さずに Service Worker をテストするための同様の機能を必要とするデベロッパーは、Chrome のデベロッパー ツールにある [ネットワークに対してバイパス] オプションを使用できます。
Chrome DevTools の [Bypass for Network] オプション

workbox-webpack-plugin

このプラグインは大幅に書き換えられ、多くの場合、「ゼロ構成」モードで使用できます。更新された API サーフェスについては、ドキュメントをご覧ください。

  • API は、GenerateSWInjectManifest の 2 つのクラスを公開するようになりました。これにより、モードの切り替えが明示的になります。一方、v2 では、swSrc の有無に基づいて動作が変化していました。
  • デフォルトでは、webpack のコンパイル パイプラインのアセットが事前キャッシュに保存されるため、globPatterns を構成する必要はありません。globPatterns を引き続き使用する理由は、webpack ビルドに含まれていないアセットを事前キャッシュする必要がある場合のみです。一般に、v3 プラグインに移行する場合は、まず以前の glob ベースの構成をすべて削除し、特に必要な場合にのみ再度追加する必要があります。

参考情報

ほとんどの移行は簡単であると考えられます。このガイドに記載されていない問題が発生した場合は、GitHub で問題を報告してお知らせください。