はじめに
業務で **FCM(Firebase Cloud Messaging)**を使ったWeb Push通知をSPAで実装する機会がありました。
この記事では、いくつかポイントを設けながら段階的に実装できるように書きたいと思います。
またLaravelと記載していますが、HTTPクライアントライブラリのGuzzleを使ってリクエストを投げるだけです。
この記事で説明する範囲
今回VueやLaravel、その他のライブラリなどの詳細な説明は省きます。あくまでもFCMを使ったフォアグラウンド・バックグラウンドへのPush通知がメインです。
FCM(Firebase Cloud Messaging)とは
公式ページには
Firebase Cloud Messaging(FCM)は、メッセージを無料で確実に送信するためのクロスプラットフォーム メッセージング ソリューションです。
と記載されています。
今回はWebを対象としますが仕組みは共通で、通知を受信する端末が一意なトークンをFCM側に発行してもらい、送信時に対象のトークンを用いてFCMを経由し、Push通知を送るという仕組みで、Firebaseが提供しているサービスの一つです。
手順
- Firebaseでのプロジェクト作成・アプリ登録
- Voluntary Application Server Identification鍵(VAPID鍵)の取得
- 通知に対するPermissionの実装
- フォアグラウンド・バックグラウンドでの通知の受信
- Guzzleでリクエストを投げる
Firebase を JavaScript プロジェクトに追加する
上記のリンクを確認しながら進めていけば問題ないかなと思います。
Laravelであれば Firebase SDK を追加して Firebase を初期化するという部分に関しては、Vueインスタンスを表示するbladeでFirebase SDKを追加しましょう。
if (!firebase.apps.length) {
firebase.initializeApp({
apiKey: process.env.MIX_FIREBASE_API_KEY,
authDomain: process.env.MIX_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.MIX_FIREBASE_DATABASE_URL,
projectId: process.env.MIX_FIREBASE_PROJECT_ID,
storageBucket: process.env.MIX_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.MIX_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.MIX_FIREBASE_APP_ID,
})
}
export default firebase
exportしてオブジェクトを各ファイルで参照できるようにしていますが、オブジェクトを使用したいファイルで直接初期化を行っても問題ありません。
2. Voluntary Application Server Identification鍵(VAPID鍵)の取得・設定
Web Push通知をWebアプリケーションに飛ばす際FirebaseプロジェクトとWebアプリケーションを紐づける必要があります。Firebaseコンソールから新しく生成する方法、既存のリソースをインポートする方法の両方用意されています。
VAPID鍵を生成・インポートしたらresource/js/App.vue
に早速コードを書いていきます。
最初に私の場合はresource/js/plugins/firebase.js
でFirebaseの初期化を行ったので、そちらのファイルをimportし、ライフサイクルの中でfirebase.messaging
を呼び出します。
これでメッセージングサービスを使用する事ができます。
import Firebase from './plugins/firebase'
export default {
created() {
const messaging = Firebase.messaging()
上記のようにメッセージオブジェクトを呼び出した後に、Voluntary Application Server Identification鍵(VAPID鍵)の取得を行った際に生成・インポートしたVAPID鍵をコードに追加します。
export default {
created() {
const messaging = Firebase.messaging()
messaging.usePublicVapidKey(process.env.MIX_FIREBASE_APP_VAPPI_KEY)
こちらのusePublicVapidKey
メソッドを使用するとFCMで各種プッシュサービスにメッセージリクエストを送信するときにVAPID鍵の認証情報を使用できます。
3. 通知に対するPermissionの実装
実際にPush通知を送信する為に、ユーザーに許可を要請する必要があります。
そのためにはrequestPermission
メソッドを使用してユーザーに対する要請の結果をPromissで取得します。
const messaging = Firebase.messaging()
messaging.usePublicVapidKey(process.env.MIX_FIREBASE_APP_VAPPI_KEY)
Notification.requestPermission()
.then(permission => {
console.log('Have permission')
})
.catch(err => {
console.log('Error Occured')
})
この段階でローカル環境の画面にアクセスすると
このような形で通知を表示のダイアログが確認できると思います。
またこの段階で許可をタップすると、ブラウザのコンソールにHave permission
と表示されることも確認できるでしょう。
次のステップに移る前にサービスワーカーファイルを作成しておきましょう。
ここではfirebase-messaging-sw.js
というファイル名で作成することが決まっているので、そのファイル名でファイルを作成したらドメインのルートに置きます。Laravelであれば、public/
配下にファイルを設置します。今は作ったファイルは空でも構いません。
4. フォアグラウンド・バックグラウンドでの通知の受信
まず始めにFCMから発行されるトークンを取得します。先ほど書いたユーザーへの許可を要請した処理で、成功した時にトークンを取得するメソッドを呼び出すだけです。
Notification.requestPermission()
.then(permission => {
console.log('Have permission')
return messaging.getToken()
})
.then(token => {
console.log(`firebase cloud messaging token: ${token}`)
})
.catch(err => {
console.log('Error Occured')
})
ここまで書いて画面にアクセスするとトークンの取得が出来ていれば
このように表示されていると思います。
前述しましたが、こちらのFCMから発行されたトークンを使用して、対象の端末に通知を表示させます。
ここでPush通知が表示される際に2つのパターンがある事を認識しておく必要があります。
- 1つ目はWebブラウザが閉じられていたり、ブラウザが閉じられていたりした場合は、3の通知に対するPermissionの実装の最後で作成したサービスワーカーファイル内でメッセージが受け取られます。
- 2つ目はユーザーがWebページを表示している時です。この場合は実際のWebページ内でメッセージを受け取ります。なのでメッセージを受け取った際に何かのイベント(ラベルやマーカーの表示)を考えている場合は、メッセージを受け取るイベントで処理を書く必要があります。
それではメッセージを受け取るために、空で作成したサービスワーカーファイルにFirebaseメッセージングService Worker定義しましょう。
messagingSenderIdには上記のFirebaseを初期化した時に利用した値を指定してあげる形で大丈夫です。
importScripts('https://www.gstatic.com/firebasejs/6.3.4/firebase-app.js')
importScripts('https://www.gstatic.com/firebasejs/6.3.4/firebase-messaging.js')
firebase.initializeApp({
messagingSenderId: 'hogehogehoge'
})
const messaging = firebase.messaging()
ここでも特に変わった事はなく、Firebaseの初期化の後にmessaging
を呼び出すだけです。
フォアグラウンドでの受信
次にこの章の目的でもあるフォアグランドでの通知の取得をonMessage
イベントを呼び出して確認してみましょう。
Notification.requestPermission()
.then(permission => {
console.log('Have permission')
return messaging.getToken()
})
.then(token => {
console.log(`firebase cloud messaging token: ${token}`)
})
.catch(err => {
console.log('Error Occured')
})
messaging.onMessage(function(payload) {
console.log('onMessage: ', payload)
})
ここまで出来たらFCMのAPIにcurlでリクエストを投げて挙動を確認してみましょう。
curl -X POST \
-H "Authorization: key={MIX_FIREBASE_SERVER_KEY}" \
-H "Content-Type: application/json" \
-d '{
"notification": {
"title": "Hello",
"body": "World",
"icon": ""
},
"to": "{firebase return token}"
}' \
"https://fcm.googleapis.com/fcm/send"
上記を実行すると
こちらのように表示されていて、通知をWebページ内で受信している事が確認できると思います。
バックグラウンドでの受信
バックグラウンドで受信する際には、通知を受信するWebページにフォーカスがない状態をブラウザで作る(別タブで他のページを閲覧している)か、他のアプリにフォーカスが当たっている状態で先ほどのリクエストを投げると挙動が確認できると思います。
確認できましたね。
今回は対象としませんが、通知オプションを設定したい場合(データペイロードを使用する場合など)はこちらを参照してください
基本的には、サービスワーカーファイルにメソッドを一つ追加して、データオプションに設定するだけです。
Guzzleでリクエストを投げる
ほぼおまけの内容ですが、先ほどのcurlで投げたリクエストを、Guzzleで投げる際のサンプルコードぐらいにみていただけると嬉しいです。
public static function handle($token, $content, $link)
{
$client = new Client();
$server_key = env('MIX_FIREBASE_SERVER_KEY');
$url = https://hogehogehogehoge;
$fcm_endpoint = 'https://fcm.googleapis.com/fcm/send';
$headers = [
'Authorization' => 'key=' . $server_key,
'Content-Type' => 'application/json'
];
$fields = [
'notification' => [
'title' => 'Sample-Notification',
'body' => $content,
'icon' => asset('img/icon/logo-main.png'),
'click_action' => $url . $link
],
'to' => $token
];
$client->post($fcm_endpoint, [
'headers' => $headers,
'json' => $fields
]);
}
最後に
今回FCMを触るきっかけとなった実装では、フォアグラウンドでの処理にvue-notificationを使用して、ユーザーになんらかのアクションを行う導線を実装したりしました。
無料で始められ手軽に実装できるので使う際の利点は多そうです。