Workbox

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

役立つタスクには、キャッシュ戦略とパス(またはルーティング パターン)のマッチング、ストリームの操作、適切なフォールバックを伴うバックグラウンド同期などの機能の使用などがあります。

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

54%

Service Worker を使用するモバイルサイトで Workbox ライブラリが使用されている

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

Workbox には、内部ではモジュールと呼ばれるいくつかのライブラリがあり、それぞれがアセットと Service Worker の動作を管理するさまざまな側面に焦点を当てています。

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

  • Service Worker のコンテキスト内: 必要なモジュールをインポートし、Service Worker ファイルから使用します。たとえば、キャッシュの管理や、さまざまな戦略によるファイルの提供に役立ちます。
  • メインの window コンテキスト内: Service Worker の登録と 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 の使用

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

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

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

npx workbox-cli wizard

ターミナルで動作している Workbox CLI

Workbox を使用したキャッシュとサービング

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-recipes] は、アーキテクチャに適したソリューションを提供している場合に参考になります。通常は 1 行のコードで、Service Worker のコードに追加する必要があります。

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

アセットをキャッシュに保存する場合は、アセットの更新も必要になります。Workbox は、最適な方法でアセットを更新するのに役立ちます。たとえば、サーバー上で変更があった場合はアプリを更新し続けることもあれば、アプリの新しいバージョンがリリースされるまで待つことなども考えられます。アップデートについて詳しくは、アップデートの章をご覧ください。

Workbox で遊ぶ

次の Codelab を使用して、Workbox をすぐに試すことができます。

リソース