Webプッシュ通知についてブラウザ間の挙動の違いを調べてみた(フロントエンド編)
こんにちは。開発 2 部 箕浦です。
現在、関わっている案件でWebプッシュ通知について調べる機会がありましたので
実装の仕方からブラウザ間の挙動の違いを調査した結果を紹介します。
本記事は、後編であるフロントエンド編になり ます。
今回はフロントエンドはReactで実装します。
Service Worker
Webプッシュ通知は、ユーザーがウェブサイトを見ている状態だけでなく、他のサイトを見ているときや、別のアプリケーションを動かしているときなどにも通知されてほしいです。
WebアプリケーションはReact(Javascript)でブラウザ上で動作するものなので、基本的にはユーザーがウェブサイトを閲覧していないときは動作しません。
そのため、Webプッシュ通知を受け取ったときの動作は、本体のWebアプリケーションとは別のプロセスで動かしておいて、プッシュ通知の処理を行う仕組みが必要となります。
その役割を担うのがService Workerです。
Service Workerは、プッシュ通知だけでなく、バックグラウンドで何か処理をさせたいときなど用途はいろいろあります。
ただし、ブラウザの種類やバージョンにより、サポート状況や挙動が変わることがありますので事前に動作確認が必要となります。
publicフォルダ配下に以下の service-worker.js
ファイルを作成します。
簡単に説明すると、
push
イベントに対して、タイトルやメッセージなどを受け取り、
showNotification を使って、デスクトップにプッシュ通知を表示します。
notificationclick
イベントに対して、通知がクリックされた際に、指定したURLへ遷移するようにしています。
addEventListener('push', (event) => {
console.log('[Service Worker] Push Received.');
console.log(`[Service Worker] Push had this data: "${event}"`);
if (!(self.Notification && self.Notification.permission === 'granted'))
return;
var data = {};
if (event.data)
data = event.data.json();
console.log(data)
self.clients.matchAll().then(clients => {
clients.forEach(client => {
client.postMessage({
data: data
});
});
});
var title = data.data['pinpoint.notification.title'];
var message = data.data['pinpoint.notification.body'];
var icon = data.data['pinpoint.notification.imageIconUrl'];
var image = data.data['pinpoint.notification.imageUrl'];
var options = {
body: message,
icon: icon,
image: image,
data: data,
};
event.waitUntil(self.registration.showNotification(title, options));
});
addEventListener('notificationclick', (event) => {
event.notification.close();
event.waitUntil(
clients.openWindow(event.notification.data.data['pinpoint.url'])
);
});
React
React側ではまず、firebase のライブラリをインストールします。
npm install firebase
App.jsに前編でFirebaseコンソールからコピーしたコードスニペットをそのまま貼り付けます。
import { initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
const firebaseConfig = {
apiKey: "APIキー",
authDomain: "webpush-c7bed.firebaseapp.com",
databaseURL: "https://webpush-c7bed.firebaseio.com",
projectId: "webpush-c7bed",
storageBucket: "webpush-c7bed.appspot.com",
messagingSenderId: "586895317040",
appId: "アプリ ID",
measurementId: "G-SPL1GEMWDJ"
};
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
同じく、以下のコードを追記します。
「サーバーキー」には、前編でFirebaseコンソールからコピーしたサーバーキーを設定します。
今回はサーバーキーや上記の設定は、ソースコードにハードコーディングしていますが、本番環境で使用する場合は、外から読み込むなどの仕組みが必要で す。
import { getMessaging, getToken, isSupported } from "firebase/messaging";
const messaging = getMessaging(app);
const vapidKey = "サーバーキー"
var registeredServiceWorker;
navigator.serviceWorker.register('/service-worker.js').then((reg) => registeredServiceWorker = reg)
function App() {
useEffect(() => {
function requestPermission() {
isSupported().then((isSupport) => {
if (!isSupport) {
console.log('Messaging is not support.');
return
}
console.log('Requesting permission...');
Notification.requestPermission().then((permission) => {
if (permission === 'granted') {
console.log('Notification permission granted.');
getTokenRequest()
}
})
})
}
async function getTokenRequest() {
// Add the public key generated from the console here.
getToken(messaging, {
vapidKey: vapidKey,
serviceWorkerRegistration: registeredServiceWorker
})
.then((currentToken) => {
if (currentToken) {
// Send the token to your server and update the UI if necessary
// ...
console.log(`token: ${currentToken}`);
// ここで取得したトークンをサーバーへ送信する
} else {
// Show permission request UI
console.log('No registration token available. Request permission to generate one.');
// ...
}
}).catch((err) => {
console.log('An error occurred while retrieving token. ', err);
// ...
});
}
requestPermission();
}, []);
return (
<div className="App">
<div>
・・・
</div>
</div>
);
}
ここまでで実装は完了です。
プッシュ通知の送信
フロントエンドをローカルで起動します。
npm run start
ブラウザが起動すると、画面上部にプッシュ通知を許可もしくはブロックするがポップアップで表示されます。
ここで許可を選択しておきます。
ブロックを選択すると、プッシュ通知が届かなくなります。
すると、トークンが払い出されます。 今回はわかりやすいようにトークンをデバッグコンソールに出力しています。
本来であれば、このトークンをサーバーへ何らかの方法で送り、サーバー側でユーザーと紐づけて管理しておきます。
今回はサーバーは省略しているので、このトークンをコピペすることにします。
今回はプッシュ通知の送信は簡単に確認するため、Amazon Pinpointのコンソール画面から送信します。
デバイストークンには先ほどコピーしたトークン
プッシュ通知サービスには「FCM」
を入力し、メッセージの内容を入れて、プッシュ通知を送信します。
送信を行うと、デスクトップの右下に無事プッシュ通知が表示されました!!
ブラウザによる挙動
ここからは、ブラウザによるプッシュ通知の挙動を確認していきます。
今回はChrome、Edge、FireFoxの3種類で確認することにします。