この Codelab では、サービス ワーカーを使用して通知を管理します。ここでの手順は、サービス ワーカーと、通知の権限のリクエストと通知の送信の基本をすでに理解していることを前提としています。通知について復習する必要がある場合は、Notifications API スタートガイドの Codelab をご覧ください。Service Worker の詳細については、Matt Gaunt の Service Worker の概要をご覧ください。
サンプルアプリをリミックスして新しいタブで表示する
埋め込みの Glitch アプリからの通知は自動的にブロックされるため、このページでアプリをプレビューすることはできません。代わりに、次のようにしてください。
- [Remix to Edit] をクリックして、プロジェクトを編集可能にします。
- サイトをプレビューするには、[アプリを表示] を押してから、[全画面表示] を押します。
Glitch が新しい Chrome タブで開きます。
この Codelab では、このページに埋め込まれた Glitch のコードに変更を加えます。ライブアプリを含む新しいタブを更新して、変更を確認します。
サンプルアプリと開始用コードを確認する
まず、新しい Chrome タブでライブアプリを確認します。
- Ctrl+Shift+J(Mac の場合は Command+Option+J)キーを押して DevTools を開きます。
[コンソール] タブをクリックします。
[フィルタ] ボックスの横にある [レベル] プルダウンで、[情報] オプションが選択されていることを確認します。
公開中のアプリの DevTools コンソールに、次のコンソール メッセージが表示されます。
TODO: Implement getRegistration()
。これは、この Codelab で実装する関数スタブからのメッセージです。
では、このページに埋め込まれた Glitch で、サンプルアプリのコードを見てみましょう。
埋め込まれた Glitch で
public/index.js
を確認します。実装する関数には、
registerServiceWorker
、getRegistration
、unRegisterServiceWorker
、sendNotification
の 4 つのスタブがあります。requestPermission
関数は、通知を送信するためのユーザーの権限をリクエストします。Notifications API Codelab のスタートガイドを実施したことがある場合は、そのrequestPermission
関数がここで使用されていることに気づくでしょう。唯一の違いは、権限リクエストを解決した後にユーザー インターフェースも更新される点です。updateUI
関数は、アプリのすべてのボタンとメッセージを更新します。initializePage
関数は、ブラウザでサービス ワーカー機能の機能検出を行い、アプリのユーザー インターフェースを更新します。スクリプトは、ページの読み込みが完了するまで待ってから、ページを初期化します。
埋め込まれた Glitch で
public/service-worker.js
を開きます。名前が示すように、このファイルを Service Worker として登録するコードをアプリに追加します。
このファイルはアプリではまだ使用されていませんが、サービス ワーカーが有効になったときにコンソールにメッセージを出力する起動コードが含まれています。
public/service-worker.js
にコードを追加して、Service Worker が通知を受信したときに通知を処理します。
Service Worker を登録する
このステップでは、ユーザーがアプリ UI で [サービス ワーカーを登録] をクリックしたときに実行されるコードを記述します。このコードは、public/service-worker.js
を Service Worker として登録します。
埋め込まれた 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
をご覧ください。ユーザーが 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 登録への参照を取得しやすくなります。
サービス ワーカーの登録機能を完了するには、サービス ワーカーの登録解除コードを追加します。
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 で [通知を送信] をクリックしたときに実行されるコードを記述します。このコードは、通知を作成し、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 の
postMessage
メソッドは、アプリから Service Worker にデータを送信します。詳しくは、postMessage に関する MDN のドキュメントをご覧ください。このコードは、
postMessage
関数にアクセスする前にnavigator.serviceWorker.controller
プロパティの存在を確認します。有効な Service Worker がない場合や、ページが強制的に更新された場合(Shift+
Reload)、navigator.serviceWorker.controller
はnull
になります。詳細については、MDN の ServiceWorker コントローラのドキュメントをご覧ください。
Service Worker で通知を処理する
このステップでは、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 自体への参照です。通知の表示はサービス ワーカーが処理するようになりましたが、ユーザーから通知の権限を取得する責任は引き続きメインのアプリ UI にあります。権限が付与されていない場合、
showNotification
によって返された Promise は拒否されます。上記のコードでは、catch
ブロックを使用して、捕捉されないPromise
拒否エラーを回避し、このエラーをより適切に処理しています。
行き詰まった場合は、glitch.com/edit/#!/codelab-notifications-service-worker-completed で完成したコードをご覧ください。
このシリーズの次の Codelab「プッシュ通知サーバーを構築する」に進みます。