Service Worker を使用して通知を管理する

Kate Jeffreys
Kate Jeffreys

この Codelab では、Service Worker を使用して 通知を管理する。 ここで説明する手順は、すでに次の知識があることを前提としています。 Service Worker と、通知権限のリクエストと通知の送信に関する基本事項について説明します。 通知について復習が必要な場合は、 Notifications API を使ってみる 説明しますService Worker について詳しくは、Matt Gaunt の Introduction to Service Worker をご覧ください

サンプルアプリをリミックスして新しいタブで表示

埋め込み Glitch アプリからの通知は自動的にブロックされるため、このページではアプリをプレビューできません。代わりに、次のようにします。

  1. [Remix to Edit] をクリックして、プロジェクトを編集可能にします。
  2. サイトをプレビューするには、[アプリを表示] を押します。[ 全画面表示 全画面表示

Glitch が新しい Chrome タブで開きます。

この Codelab を進めながら、このページに埋め込まれた Glitch のコードを変更します。ライブアプリで新しいタブを更新して、変更を確認します。

サンプルアプリと開始用コードに慣れる

まず、新しい Chrome タブでライブアプリを確認します。

  1. Ctrl+Shift+J キー(Mac の場合は Command+Option+J キー)を押して DevTools を開きます。
  2. [コンソール] タブをクリックします。

  3. [Levels] プルダウンで [Info] が選択されていることを確認します。 [フィルタ] ボックスの横。

  4. ライブアプリの DevTools コンソールに、コンソール メッセージが表示されます。

    TODO: Implement getRegistration()

    これは、この Codelab で実装する関数スタブからのメッセージです。

次に、このページに埋め込まれた Glitch にあるサンプルアプリのコードを見てみましょう。

  1. 埋め込まれた Glitch で public/index.js を見てみましょう。

    • 実装する関数のスタブは 4 つあります(registerServiceWorkergetRegistrationunRegisterServiceWorkersendNotification)。

    • requestPermission 関数が、通知を送信する許可をユーザーにリクエストします。Notifications API スタートガイドの Codelab を完了している場合、ここではその requestPermission 関数が使用されていることにお気づきでしょう。唯一の違いは、権限リクエストの解決後にユーザー インターフェースも更新されるようになったことです。

    • updateUI 関数は、アプリのすべてのボタンとメッセージを更新します。

    • initializePage 関数は、ブラウザで Service Worker 機能の機能検出を実行し、アプリのユーザー インターフェースを更新します。

    • このスクリプトは、ページが読み込まれるのを待ってから、初期化します。

  2. 埋め込まれた Glitch で public/service-worker.js を開きます。

    名前が示すように、このファイルをファイルとして登録するコードをアプリに追加します。 Service Worker

    このファイルはまだアプリでは使用されませんが、Service Worker がアクティブになったときにコンソールにメッセージを出力する開始コードが含まれています。

    Service Worker が通知を受信したときに通知を処理するコードを public/service-worker.js に追加します。

Service Worker を登録する

このステップでは、Kubernetes の ユーザーがアプリの UI で [Register Service Worker] をクリックしたとき。 このコードは、public/service-worker.js を Service Worker として登録します。

  1. 埋め込みの Glitch エディタで public/index.js を開きます。 registerServiceWorker 関数を次のコードに置き換えます。

    // Use the Service Worker API to register a service worker.
    async function registerServiceWorker() {
      await navigator.serviceWorker.register('./service-worker.js')
      updateUI();
    }
    

    なお、registerServiceWorker では async function 宣言を使用して、Promise の処理を便利にしています。これにより、Promise の解決済み値を await できます。たとえば、上記の関数は Service Worker の登録結果を待機してから UI を更新します。詳しくは、MDN の await をご覧ください。

  2. これで、ユーザーが Service Worker を登録できるようになったので、Service Worker 登録オブジェクトへの参照を取得できます。public/index.js で、getRegistration 関数を次のコードに置き換えます。

    // Get the current service worker registration.
    function getRegistration() {
      return navigator.serviceWorker.getRegistration();
    }
    

    上記の関数では Service Worker API 現在の Service Worker の登録情報を取得します(存在する場合)。 これにより、Service Worker 登録への参照を少し簡単に取得できます。

  • Service Worker の登録機能を完成させるには、Service Worker の登録を解除するコードを追加します。unRegisterServiceWorker 関数を次のコードに置き換えます。

    // Unregister a service worker, then update the UI.
    async function unRegisterServiceWorker() {
      // Get a reference to the service worker registration.
      let registration = await getRegistration();
      // Await the outcome of the unregistration attempt
      // so that the UI update is not superceded by a
      // returning Promise.
      await registration.unregister();
      updateUI();
    }
    

ライブアプリが表示されているタブで、ページを再読み込みします。[Service Worker の登録] と [Service Worker の登録解除] ボタンが機能するはずです。

Service Worker に通知を送信する

このステップでは、ユーザーがアプリ UI で [Send a notification] をクリックしたときに実行されるコードを記述します。このコードは、通知を作成し、Service Worker が登録されていることを確認してから、postMessage メソッドを使用して通知を Service Worker に送信します。

埋め込みの Glitch エディタで public/index.js を開きます。 sendNotification 関数を次のコードに置き換えます。

// Create and send a test notification to the service worker.
async function sendNotification() {
  // Use a random number as part of the notification data
  // (so you can tell the notifications apart during testing!)
  let randy = Math.floor(Math.random() * 100);
  let notification = {
    title: 'Test ' + randy,
    options: { body: 'Test body ' + randy }
  };
  // Get a reference to the service worker registration.
  let registration = await getRegistration();
  // Check that the service worker registration exists.
  if (registration) {
    // Check that a service worker controller exists before
    // trying to access the postMessage method.
    if (navigator.serviceWorker.controller) {
      navigator.serviceWorker.controller.postMessage(notification);
    } else {
      console.log('No service worker controller found. Try a soft reload.');
    }
  }
}

このコードの機能は次のとおりです。

  • sendNotification は非同期関数であるため、await を使用して Service Worker 登録への参照を取得できます。

  • Service Worker の postMessage メソッドは、アプリから Service Worker にデータを送信します。詳細については、postMessage の MDN ドキュメントをご覧ください。

  • このコードでは、postMessage 関数にアクセスする前に、navigator.serviceWorker.controller プロパティが存在するかどうかを確認します。アクティブな Service Worker がない場合、またはページが強制的に更新された場合(Shift+再読み込み)、navigator.serviceWorker.controllernull になります。詳細については、MDN の ServiceWorker コントローラのドキュメントをご覧ください。

Service Worker で通知を処理する

このステップでは、Service Worker にポストされたメッセージを処理し、ユーザーに通知を表示するコードを記述します。

埋め込みの Glitch エディタで public/service-worker.js を開きます。ファイルの末尾に次のコードを追加します。

// Show notification when received
self.addEventListener('message', (event) => {
  let notification = event.data;
  self.registration.showNotification(
    notification.title,
    notification.options
  ).catch((error) => {
    console.log(error);
  });
});

簡単に説明します。

  • self は、Service Worker 自体への参照です。

  • Service Worker が通知の表示を処理するようになりましたが、メインアプリの UI は引き続きユーザーから通知権限を取得します。権限が付与されていない場合、showNotification によって返される Promise は拒否されます。上記のコードでは、catch ブロックを使用して、捕捉されない Promise 拒否エラーを回避し、このエラーを適切に処理しています。

行き詰まった場合は、glitch.com/edit/#!/codelab-notifications-service-worker-completed の完成したコードをご覧ください。

このシリーズの次の Codelab「プッシュ通知サーバーを作成する」に進みます。