プッシュ通知は、現代の Web ではよく見られるものです。これにより、サイトが実際に開いていない場合でも、タイムリーな情報をユーザーに伝えることができます。ユーザーのブラウザは受信プッシュ イベントを処理し、Windows アクション センターや Android ロック画面などのシステム UI サーフェスを使用して通知を表示します。
Web プッシュをサイト または PWA に実装するには、2 つの異なるブラウザー API を組み合わせる必要があります。通知のサブスクライブと受信を担当するコードは 、Service Worker の Push API コンポーネントを使用します。このコードはバックグラウンドで継続的に実行され、新しい通知を処理する必要があるときにブラウザーによって呼び出されます。
イベントを受信すると、Service Worker は 通知 API を使用して実際に通知を表示する必要があります。これにより、OS レベルのインターフェイスを介して視覚的なアラートが作成されます。
これは、サイトで Web プッシュを機能させるための完全なガイドです。プッシュ サブスクリプションを登録し、アラートを送信できるサーバー側コンポーネントがすでにあると仮定します。
サービスワーカー
サービスワーカーから始めましょう。 Service Worker には複数の役割があります。オフラインで使用するためにデータをキャッシュしたり、定期的なバックグラウンド同期を実行したり、通知ハンドラーとして機能したりできます。 Service Worker はイベント駆動型のアーキテクチャを使用します。サイトによって登録されると、ユーザーのブラウザーは、サブスクライブするイベントが生成されるときにバックグラウンドで Service Worker を呼び出します。
Web プッシュの場合、1 つのコア イベントが必要です。
push
PushEvent
サーバーからプッシュされたペイロードにアクセスできるようにするオブジェクト。
self.addEventListener("プッシュ", e => {
const ペイロード = JSON.parse(e.data.text());
e.waitUntil(self.registration.showNotification(
ペイロード.タイトル、
{
ボディ: ペイロード.ボディ、
アイコン: “/icon.png”
}
));
});
上記のコードは、受信プッシュ イベントに反応できる Service Worker をセットアップします。サーバーは次のような JSON ペイロードを送信することが期待されます。
{
“title”: “通知のタイトルテキスト”,
“body”: “これは通知の長いテキストです。”
}
プッシュ イベントを受信すると、Service Worker は、
showNotification()
で利用できる機能
self .registration
財産。関数は
waitUntil()
を呼び出すと、ブラウザーは Service Worker を終了する前に通知が表示されるのを待ちます。
の
showNotification()
この関数は、通知のタイトル テキストとオプション オブジェクトの 2 つの引数を取ります。この例では、長い本文テキストと通知に表示するアイコンという 2 つのオプションが渡されます。振動パターン、カスタムバッジ、インタラクション要件を設定できる 他の多くのオプション が利用可能です。すべてのブラウザーとオペレーティング システムが、API によって公開されるすべての機能をサポートしているわけではありません。
コードをメインの JavaScript に登録し直して、サービス ワーカー側のコードを完成させます。
if (navigator.serviceWorker) {
// Service Worker ファイルへのパスに置き換えます
navigator.serviceWorker.register(“/sw.js”).catch(() => {
console.error(“サービスワーカーを登録できませんでした。”)
});
}
このコードは、ページが読み込まれるたびに実行される必要があります。ブラウザーが Service Worker をサポートしていることを確認してから、Worker ファイルを登録します。ブラウザーは、サーバーのコピーに現在インストールされているバージョンとのバイトの違いが見られるたびに、Service Worker を自動的に更新します。
プッシュサブスクリプションへの登録
次に、ブラウザーをプッシュ通知に登録する必要があります。次のコードは、Service Worker の外側のメイン JavaScript ファイルに属します。
非同期関数subscribeToPush() {
if (navigator.serviceWorker) {
const reg = await navigator.serviceWorker.getRegistration();
if (reg && reg.pushManager) {
const subscription = await reg.pushManager.getSubscription();
if (!サブスクリプション) {
const key = await fetch(“https://example.com/vapid_key”);
const keyData = await key.text();
const sub = await reg.pushManager.subscribe({
applicationServerKey: keyData、
userVisibleOnly: true
});
await fetch(“https://example.com/push_subscribe”, {
メソッド: “POST”、
ヘッダー: {“Content-Type”: “application/json”},
本文: JSON.stringify({
エンドポイント: sub.endpoint、
有効期限: sub.expirationTime、
キー: sub.toJSON().keys
})
});
}
}
}
}
次に、関数を呼び出してブラウザーをプッシュ通知にサブスクライブします。
submitToPush() を待ちます。
サブスクリプション コードが何をしているのかを見てみましょう。最初の数行は、Service Worker の存在を確認し、その登録を取得し、プッシュ通知サポートを検出します。
pushManager
Web Pushをサポートしていないブラウザでは設定されません。
電話をかける
pushManager .getSubscription ()
サイトに対するブラウザーの現在のプッシュ サブスクリプションを記述するオブジェクトに解決される Promise を返します。これがすでに設定されている場合は、ユーザーを再登録する必要はありません。
実際のサブスクリプション フローは、サーバーの VAPID キーのフェッチ リクエストから始まります。 VAPID 仕様は、プッシュ イベントが実際にサーバーから送信されたものであることをブラウザーが検証できるようにする メカニズムです 。 VAPID キーを提供するサーバー API エンドポイントを公開する必要があります。これは、
pushManager .subscribe ()
ブラウザが信頼できるキーを認識できるように機能します。別個の
userVisibleOnly
オプションは、画面に表示される通知のみを表示することを示します。
の
pushManager .subscribe ()
PushSubscription
新しいサブスクリプションを説明するオブジェクト。このデータは、別のフェッチ リクエストでサーバーに送信されます。実際のアプリでは、アクティブなユーザーの ID も送信して、プッシュ サブスクリプションをデバイスにリンクできるようにします。
ユーザーにプッシュ通知を送信するためのサーバー側のコードは次のようになります。
- ターゲット ユーザーにリンクされているすべてのプッシュ サブスクリプションについてデータ ストアをクエリします。
-
サブスクリプションの認証キー (
購読時にブラウザによって送信されるデータに含まれます)。ブラウザに送信したのと同じ VAPID キーを使用してイベントに署名します。keys
各サブスクリプションの
endpoint
ブラウザ ベンダーの通知配信プラットフォームを参照します。この URL には、サブスクリプションの一意の識別子がすでに含まれています。エンドポイントにペイロードを送信すると、最終的にブラウザーのバックグラウンド プロセスがデータを受信し、Service Worker を呼び出します。 Android 上の Chrome の場合、ブラウザ プロセスはシステム通知デーモンと直接統合されています。
ユーザーをいつ購読するか?
サブスクリプション フローを設定するときは、登録が完了する前にユーザーがブラウザーの許可プロンプトに同意する必要があることに注意してください。多くのブラウザは、一方的な許可リクエストを 自動的に非表示にするか 拒否します。いずれにせよ、ユーザーがサイトにアクセスした瞬間に購読するように要求しても、期待する結果が得られない可能性があります。
サブスクリプション要求をユーザーの直接アクションに結び付けることで、サインアップが成功する可能性が最も高くなります。通知を有効にするメリットを説明し、「今すぐ有効にする」ボタンを提供するアプリ内バナーを提供することを検討してください。ユーザーがすでに購読しているかどうかを確認し、バナーを非表示にすることができます。
pushManager .getSubscription ()
上に示した関数。
有効化ボタンをクリックすると、サブスクリプション関数が呼び出されます。ブラウザが登録をセットアップし、ネットワーク呼び出しが完了するまで、このプロセスには数秒かかる場合があります。この間に読み込みスピナーを表示すると、ユーザーに情報を提供し続けるのに役立ちます。
ユーザーには購読を解除する方法も提供される必要があります。ブラウザーの許可はいつでも取り消すことができますが、一部のユーザーは、特にサイトを PWA としてインストールしている場合は、アプリ内オプションを探します。
簡単な購読解除の実装は次のとおりです。
非同期関数 unsubscribePush() {
const reg = await navigator.serviceWorker.getRegistration();
const subscription = await reg.pushManager.getSubscription();
if (サブスクリプション) {
サブスクリプションを待つ.unsubscribe();
await fetch(`https://example.com/push_unsubscribe/${subscription.endpoint}`, {メソッド: “DELETE”});
}
それ以外 {
// すでに購読されています
}
}
電話をかける
unsubscribe()
に
PushSubscription
サブスクリプションをキャンセルし、ブラウザをデフォルトの状態に戻します。 Service Worker が受信を停止します
push
イベント。サブスクリプションのエンドポイントはサーバーに送信されるため、データ ストアからエンドポイントを削除し、現在無効になっている URL にデータを送信することを回避できます。
有効期限と更新の処理
お気づきかもしれませんが、
expirationTime
PushSubscription
ブラウザによって作成されたオブジェクト。これは常に設定されるわけではありません。そうである場合、デバイスはこの時間が経過すると通知の受信を停止します。
実際には、
expirationTime
現在、主要なブラウザでは使用されていません。 Chrome によって生成されたトークンは、手動で登録を解除するまで 有効期限が切れません 。
expirationTime
いつも
null
。 Firefoxが設定できない
expirationTime
どちらでも構いませんが、通知サービスは有効期間中にサブスクリプションを置き換えることができます。
を実装することで、アクティブなプッシュ サブスクリプションを変更するブラウザーに応答できます。
pushsubscriptionchange
Service Worker 内のイベント。残念ながら、このイベントには 2 つのバージョンがあります。現在 Firefox で使用されているオリジナルの実装と、まだどのブラウザでもサポートされていない新しい v2 です。
元の仕様にはユーザビリティに重大な問題があり、イベントへの対応が困難になります。 v1 イベントを受信すると、ブラウザーは元のサブスクリプションを削除しているため、新しいサブスクリプションを手動で作成する必要があります。問題は、期限切れのサブスクリプションにアクセスできないと、サーバーに「置換」リクエストを発行できないことです。古いサブスクリプションにアクセスする方法がありません。
endpoint
URL。
v2 仕様では、イベントを提供することでこれを解決します。
oldSubscription
そして
newSubscription
プロパティ。イベントを受信すると、古いサブスクリプションはキャンセルされていますが、そのプロパティには引き続きアクセスできます。新しいサブスクリプションがブラウザーによって作成されます。
実装例は次のとおりです
pushsubscriptionchange
新しい仕様では:
self.addEventListener("pushsubscriptionchange", e => {
e.waitUntil(async () => {
await fetch(“https://example.com/push_change”, {
メソッド: “POST”、
ヘッダー: {
「コンテンツタイプ」: 「アプリケーション/json」
}、
本文: JSON.stringify({
認証: (e.newSubscription.toJSON().keys?.auth || null)、
エンドポイント: e.newSubscription.endpoint、
エンドポイント古い: e.oldSubscription.endpoint,
有効期限: e.newSubscription.expirationTime、
p256dh: (e.newSubscription.toJSON().keys?.p256dh || null)
})
});
});
});
エンドポイントは一意であるため、サーバーは古いサブスクリプションを検索し、そのプロパティを新しいサブスクリプションのプロパティで更新できます。古い仕様のサポートも追加したい場合は、プッシュ API の外部でアクティブなサブスクリプション エンドポイントを手動で追跡する必要があります。に保存する
localStorage
または、IndexedDB を使用すると、内部でアクセスできます。
pushsubscriptionchange
これにより、サーバーにサブスクリプションを置き換えるように要求できるようになります。
改訂された仕様は、古い仕様よりも実装がはるかに簡単です。ブラウザーではまだサポートされていませんが、とにかく Service Worker に追加する価値があります。数行のコードにより、新しいブラウザのリリースに対してプッシュ処理を将来的に保証することができます。
アクションボタンの追加
プッシュ通知には、ユーザーが即座にアクションを実行できる対話型ボタンを含めることができます。ここにあります
showNotification()
これを呼び出すと、次のものが作成されます。
self.registration.showNotification(
“アクション付き通知”,
{
body: “この通知にはボタンがあります。”,
行動: [
{
アクション: “/home”、
タイトル: “ホーム画面に移動”,
アイコン:「/home.png」
}
】
}
);
各通知には複数のアクションを含めることができ、それぞれにラベル、アイコン、
action
。後者のプロパティは、ユーザーの押下に応じてアプリが開始できるアクションを識別する必要があります。
ユーザーがアクションをタップすると、Service Worker は
notificationclick
イベント:
self.addEventListener("notificationclick", e => {
const uri = e.action;
const notification = e.notification;
通知.close();
client.openWindow(`${self.location.origin}${action}`);
});
私たちが使用しているのは、
action
プロパティを使用して、ユーザーが移動できる URI を宣言します。通知が押されると、その URI に新しいタブが開きます。電話をかける
notification .close ()
通知も確実に無視されます。そうしないと、一部のプラットフォームではユーザーが手動でスワイプする必要があります。
まとめ
これまでに関連する API を使用したことがない場合、Web プッシュの実装は難しく思えるかもしれません。技術的な懸念よりも、ユーザー エクスペリエンスを常に念頭に置き、通知を有効にする価値がある理由を確実に伝える必要があります。
プッシュのサブスクライブとサブスクライブ解除は、アプリケーションのメイン JavaScript コードで行われます。
navigator .serviceWorker
API。新しいプッシュ イベントに応答し、ブラウザ通知を表示するコードは、Service Worker 自体に存在します。
Web プッシュは現在、ほとんどの主要な Web ブラウザでサポートされていますが、Safari は例外です。通知の表示方法はブラウザーやオペレーティング システム ファミリごとに異なるため、通知の特定の機能を想定しないでください。
showNotification()
API は世界中で利用できるようになります。





