Service Worker の操作

このコードラボでは、ウェブ アプリケーション内から Service Worker を登録し、Chrome DevTools を使用してその動作をモニタリングする方法について説明します。また、Service Worker を扱う際に役立つデバッグ手法についても説明します。

この Codelab に最も関連するサンプル プロジェクトのファイルは次のとおりです。

  • register-sw.js は最初は空ですが、Service Worker の登録に使用されるコードが含まれます。プロジェクトの index.html 内の <script> タグによってすでに読み込まれています。
  • service-worker.js も同様に空です。このファイルには、このプロジェクトの Service Worker が含まれます。

Service Worker の登録コードを追加する

Service Worker(現在の service-worker.js ファイルのような空の Service Worker でも)は、事前に登録されていない限り使用されません。次の呼び出しで実行できます。

navigator.serviceWorker.register(
  '/service-worker.js'
)

register-sw.js ファイル内

ただし、そのコードを追加する前に、考慮すべき点がいくつかあります。

まず、すべてのブラウザが Service Worker をサポートしているわけではありません。これは、自動更新されない古いバージョンのブラウザに特に当てはまります。したがって、navigator.serviceWorker がサポートされているかどうかを確認してから、navigator.serviceWorker.register() を条件付きで呼び出すことをおすすめします。

2 つ目は、Service Worker を登録すると、ブラウザが service-worker.js ファイル内のコードを実行し、Service Worker の install イベント ハンドラと activate イベント ハンドラのコードに応じて、URL のダウンロードを開始してキャッシュに格納する可能性があることです。

追加のコードの実行やアセットのダウンロードによって、ブラウザが現在のウェブページの表示に使用できる貴重なリソースが消費される可能性があります。この干渉を回避するには、ブラウザが現在のページのレンダリングを完了するまで Service Worker の登録を遅らせることをおすすめします。これを近似する便利な方法は、window.load イベントが発生するまで待機することです。

これら 2 つのポイントを合わせ、次の汎用 Service Worker 登録コードを register-sw.js ファイルに追加します。

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/service-worker.js');
  });
}

Service Worker のロギングコードを追加する

通常、service-worker.js ファイルには、サービス ワーカーの実装に関するすべてのロジックが記述されます。サービス ワーカーのライフサイクル イベントCache Storage API、ウェブアプリのネットワーク トラフィックに関する知識を組み合わせて、ウェブアプリのすべてのリクエストを処理する完璧なサービス ワーカーを作成します。

ただし、この段階では、さまざまな Service Worker イベントを監視し、Chrome の DevTools を使用して Service Worker の状態をデバッグすることに重点を置きます。

そのためには、service-worker.js に次のコードを追加します。これにより、さまざまなイベントに応じて DevTools コンソールにメッセージがログに記録されます(それ以外の処理は行われません)。

self.addEventListener('install', (event) => {
  console.log('Inside the install handler:', event);
});

self.addEventListener('activate', (event) => {
  console.log('Inside the activate handler:', event);
});

self.addEventListener(fetch, (event) => {
  console.log('Inside the fetch handler:', event);
});

DevTools の [Service Workers] パネルについて理解する

register-sw.js ファイルと service-worker.js ファイルにコードを追加したので、サンプル プロジェクトの公開版にアクセスして、サービス ワーカーの動作を確認しましょう。

  • サイトをプレビューするには、[アプリを表示] を押してから、[全画面表示] 全画面表示 を押します。
  • Ctrl+Shift+J(Mac の場合は Command+Option+J)キーを押して DevTools を開きます。
  • [コンソール] タブをクリックします。

次のようなログメッセージが表示され、Service Worker がインストールされ、有効になっていることを確認できます。

Service Worker がインストールされ、有効になっていることを示します。

次に、[アプリケーション] タブに移動し、[Service Workers] パネルを選択します。次のような画面が表示されます。

Service Worker パネルに Service Worker の詳細を表示します。

これは、ウェブアプリ solar-donkey.glitch.me のソース URL が service-worker.js の Service Worker が現在アクティブで実行されていることを示しています。また、現在 Service Worker によって制御されているクライアント(開いているタブ)が 1 つあることもわかります。

このパネルのリンク(Unregisterstop など)を使用して、デバッグ目的で現在登録されている Service Worker を変更できます。

Service Worker の更新フローをトリガーする

サービス ワーカーを使用して開発する際に理解すべき重要なコンセプトの 1 つは、更新フローの考え方です。

ユーザーがサービス ワーカーを登録するウェブアプリにアクセスすると、ローカル ブラウザに service-worker.js の現在のコピーのコードがインストールされます。ウェブサーバーに保存されている service-worker.js のバージョンを更新するとどうなりますか?

リピーターがサービス ワーカーのスコープ内の URL に戻ると、ブラウザは最新の service-worker.js を自動的にリクエストし、変更がないか確認します。Service Worker スクリプトに何か違いがある場合、新しい Service Worker はインストール、有効化、最終的には制御を取得できます。

プロジェクトのコードエディタに戻り、コードをなんらかの変更を加えることで、このアップデート フローをシミュレートできます。簡単に変更できる点としては、

self.addEventListener('install', (event) => {
  console.log('Inside the install handler:', event);
});

self.addEventListener('install', (event) => {
  console.log('Inside the UPDATED install handler:', event);
});

変更を加えた後、サンプルアプリの公開版に戻り、DevTools の [Application] タブを開いたままページを再読み込みします。次のような画面が表示されます。

インストールされている Service Worker の 2 つのバージョンが表示されます。

これは、この時点でインストールされている Service Worker に 2 つのバージョンがあることを示しています。すでに有効になっている以前のバージョンが実行され、現在のページを制御しています。更新されたバージョンのサービス ワーカーは、すぐ下に表示されます。waiting 状態で、古い Service Worker によって制御されている開いているタブがすべて閉じられるまで待機します。

このデフォルトの動作により、新しいサービス ワーカーの動作が古いサービス ワーカーと根本的に異なる場合(古いバージョンのウェブアプリと互換性のないリソースで応答する fetch ハンドラなど)は、ユーザーがウェブアプリの以前のインスタンスをすべてシャットダウンするまで、新しいサービス ワーカーは有効になりません。

まとめ

これで、Service Worker の登録プロセスと、Chrome の DevTools を使用して Service Worker の動作をモニタリングするプロセスを理解できたはずです。

これで、キャッシュ戦略の実装を始めることができます。また、ウェブアプリの高速かつ信頼性の高い読み込みに役立つすべての機能を実装できます。