Workbox

PWA が拡大するにつれて、Service Worker とキャッシュ ストレージ ロジックのメンテナンスが難しくなることがあります。Workbox は、作業を支援する一連のオープンソース ライブラリです。Workbox は、Service Worker API や Cache Storage API などの低レベル API をカプセル化し、よりデベロッパーにとって使いやすいインターフェースを公開しています。

キャッシュ戦略をパス(またはルーティング パターン)に一致させる、ストリームを操作する、適切なフォールバックを伴うバックグラウンド同期などの機能を使用するといったタスクを行うことができます。

ワークボックスは、アセットのキャッシュ保存と配信のニーズの管理に役立ちます。また、Service Worker で最もよく使用されているライブラリでもあります。モバイルサイトの 54% で使用され、Angular CLI、Create-React-App、Vue CLI など、多くのビルドツールや CLI で使用されています。Next.js など、他のほとんどのライブラリやフレームワークにもプラグインがあります。

54%

Service Worker があるモバイルサイトではワークボックス ライブラリを使用する

ワークボックス モジュール

ワークボックスには複数のライブラリ(内部ではモジュールと呼ばれる)が含まれています。ライブラリはそれぞれ、アセットと Service Worker の動作を管理するためのさまざまな側面に焦点を当てています。

ワークボックス モジュールは、次のようなさまざまなコンテキストで動作します。

  • Service Worker のコンテキスト内: 必要なモジュールをインポートし、Service Worker ファイルから使用します。たとえば、キャッシュの管理や、さまざまな戦略によるファイルの提供に役立てることができます。
  • メインの window コンテキスト内: Service Worker の登録とそれとの通信
  • ビルドシステムの一部として使用する: たとえば、アセットのマニフェストの作成や、Service Worker 全体の生成などの目的で webpack を使用します。

よく使用されるモジュールは次のとおりです。

  • workbox-routing: Service Worker がリクエストをインターセプトすると、このモジュールはレスポンスを提供する別の関数にリクエストをルーティングします。これは、サービングの章で説明した fetch イベント ハンドラの実装です。
  • workbox-strategies: リクエストへの応答を処理する一連のランタイム キャッシュ戦略(キャッシュ優先、再検証中の古いキャッシュなど)。これは、サービングの章で説明したさまざまな戦略を実装したものです。
  • workbox-precaching: キャッシュに関する章で説明されているように、Service Worker の install イベント ハンドラでファイルをキャッシュする実装(プレキャッシュとも呼ばれます)です。このモジュールを使用すると、一連のファイルを簡単に事前キャッシュし、それらのアセットの更新を効率的に管理できます。アセットの更新については、更新のチャプターで説明します。
  • workbox-expiration: キャッシュ内のアイテム数やキャッシュ リクエストの経過時間に基づいて、キャッシュに保存されたリクエストを削除するためのキャッシュ保存方式のプラグインです。キャッシュの管理に役立ち、時間と各キャッシュ内のアイテム数に上限を設定できます。
  • workbox-window: ウィンドウ コンテキスト、つまり PWA ウェブページ内で実行される一連のモジュール。これにより、Service Worker の登録と更新のプロセスを簡素化し、Service Worker コンテキストで実行されているコードとウィンドウ コンテキストで実行されるコード間の通信が容易になります。

ワークボックスの使用

Workbox では、さまざまな方法で PWA に統合できます。アプリのアーキテクチャに最適なものを選択できます。

  • Workbox CLI: 完全な Service Worker の生成、プリキャッシュ マニフェストの挿入、必要なワークボックス ファイルのコピーを行うコマンドライン ユーティリティ。
  • Workbox ビルド: 完全な Service Worker を生成し、プリキャッシュ マニフェストを挿入して、Workbox ファイルをコピーする npm モジュール。これは、独自のビルドプロセスに統合することを目的としています。
  • workbox-sw: Workbox Service Worker パッケージを、ビルドプロセスを使用しない CDN から読み込む方法。

Workbox CLI には、Service Worker を作成するためのウィザードが用意されています。ウィザードを実行するには、コマンドラインで次のコマンドを入力します。

npx workbox-cli wizard

ターミナルで動作しているワークボックス CLI

ワークボックスを使用したキャッシュ保存とサービス提供

Workbox の一般的な用途は、ルーティング モジュールと戦略モジュールを併用してファイルをキャッシュに保存し、配信することです。

モジュール workbox-strategies には、アセットとデータサービングの章で説明したキャッシュ戦略がデフォルトで用意されています。

workbox-routing モジュールは、Service Worker への受信リクエストを分類し、それらをキャッシュ戦略または関数と照合して、それらのリクエストに対するレスポンスを得るのに役立ちます。

ルートと戦略が一致すると、Workbox では workbox-cacheable-response プラグインを使用して、キャッシュに追加するレスポンスをフィルタすることもできます。このプラグインを使用すると、たとえばエラーなしで返されたレスポンスのみをキャッシュに保存できます。

次のコードサンプルでは、(CacheFirst モジュールを介して)キャッシュ ファースト戦略を使用して、ページ ナビゲーションをキャッシュに保存して配信します。

import { registerRoute } from 'workbox-routing';
import { CacheFirst } from 'workbox-strategies';
import { CacheableResponsePlugin } from 'workbox-cacheable-response';

const pageStrategy = new CacheFirst({
  // Put all cached files in a cache named 'pages'
  cacheName: 'pages',
  plugins: [
    // Only requests that return with a 200 status are cached
    new CacheableResponsePlugin({
      statuses: [200],
    }),
  ],
});

このプラグインを使用すると、Workbox のキャッシュ保存とリクエスト解決のライフサイクルを利用できます。ここでは、CacheableResponsePlugin を使用して、ステータスが 200 になったリクエストのみをキャッシュに保存し、不正なリクエストがキャッシュに保存されないようにします。

戦略を作成したら、それを使用するルートを登録します。次の例では、registerRoute() を呼び出して Request オブジェクトをコールバックに渡します。request.mode"navigate" の場合は、前のコードサンプルで定義されている CacheFirst 戦略(ここでは pageStrategy)が使用されます。

// Cache page navigations (HTML) with a Cache First strategy
registerRoute( ({ request }) => request.mode === 'navigate',
  pageStrategy );

その他の例やおすすめの方法については、Workbox のドキュメントをご覧ください。

オフラインの代替

workbox-routing モジュールには、エクスポートされた setCatchHandler() も含まれています。これは、ルートがエラーをスローした場合に対処します。これを使用してオフラインのフォールバックを設定し、リクエストしたルートが現在利用できないことをユーザーに知らせることができます。

ここでは、Workbox と Cache Storage API を組み合わせて使用することで、キャッシュのみの戦略を使用したオフライン フォールバックを実現できます。 まず、Service Worker のインストールのライフサイクル中に、offline-fallbacks キャッシュが開き、オフライン フォールバックの配列がキャッシュに追加されます。

import { setCatchHandler } from 'workbox-routing';

// Warm the cache when the service worker installs
self.addEventListener('install', event => {
  const files = ['/offline.html']; // you can add more resources here
  event.waitUntil(
    self.caches.open('offline-fallbacks')
        .then(cache => cache.addAll(files))
  );
});

次に、setCatchHandler() で、エラーが発生したリクエストの宛先が特定され、offline-fallbacks キャッシュが開かれます。エクスポート先がドキュメントの場合は、オフライン フォールバックの内容がユーザーに返されます。その要素が存在しない場合、または参照先がドキュメント(画像やスタイルシートなど)ではない場合は、エラー レスポンスが返されます。このパターンは、ドキュメントだけでなく、画像、動画、フォントなど、オフラインの代替手段として提供したいあらゆるものに適用できます。

// Respond with the fallback if a route throws an error
setCatchHandler(async (options) => {
  const destination = options.request.destination;
  const cache = await self.caches.open('offline-fallbacks');
  if (destination === 'document') {
    return (await cache.match('/offline.html')) || Response.error();
  }
  return Response.error();
});

レシピ

NetworkFirst ナビゲーションやオフライン フォールバックなど、いくつかのルーティングとキャッシュのパターンは一般的であり、再利用可能なレシピにカプセル化できます。workbox-recipe が、ご使用のアーキテクチャに適したソリューションを提供する場合に役立つため、こちらを確認してください。これらは通常、1 行のコードとして提供され、Service Worker のコードに追加する必要があります。

アセットのキャッシュ保存と更新

アセットをキャッシュに保存するには、アセットの更新も必要になります。ワークボックスは、最適な方法でアセットを更新するのに役立ちます。たとえば、サーバーで変更が行われた場合にアップデートを維持する、アプリの新しいバージョンが公開されるまで待機する、などです。 更新について詳しくは、更新の章をご覧ください。

ワークボックスで遊ぶ

次の Codelab を使用すると、Workbox をすぐに使用できます。

リソース