13
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Vue + Laravel + Firebaseで始めるWeb Push通知

Last updated at Posted at 2020-07-05

はじめに

業務で **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が提供しているサービスの一つです。

手順

  1. Firebaseでのプロジェクト作成・アプリ登録
  2. Voluntary Application Server Identification鍵(VAPID鍵)の取得
  3. 通知に対するPermissionの実装
  4. フォアグラウンド・バックグラウンドでの通知の受信
  5. Guzzleでリクエストを投げる

Firebase を JavaScript プロジェクトに追加する
上記のリンクを確認しながら進めていけば問題ないかなと思います。
Laravelであれば Firebase SDK を追加して Firebase を初期化するという部分に関しては、Vueインスタンスを表示するbladeでFirebase SDKを追加しましょう。

``` また初期化に関しては、私の場合`resource/js/plugins/firebase.js`などのようにディレクトリを構成し、
firebase.js
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コンソールから新しく生成する方法、既存のリソースをインポートする方法の両方用意されています。
鍵生成.png

VAPID鍵を生成・インポートしたらresource/js/App.vueに早速コードを書いていきます。
最初に私の場合はresource/js/plugins/firebase.jsでFirebaseの初期化を行ったので、そちらのファイルをimportし、ライフサイクルの中でfirebase.messagingを呼び出します。
これでメッセージングサービスを使用する事ができます。

App.vue
import Firebase from './plugins/firebase'

export default {
    created() {
        const messaging = Firebase.messaging()

上記のようにメッセージオブジェクトを呼び出した後に、Voluntary Application Server Identification鍵(VAPID鍵)の取得を行った際に生成・インポートしたVAPID鍵をコードに追加します。

App.vue
export default {
    created() {
        const messaging = Firebase.messaging()
        messaging.usePublicVapidKey(process.env.MIX_FIREBASE_APP_VAPPI_KEY)

こちらのusePublicVapidKeyメソッドを使用するとFCMで各種プッシュサービスにメッセージリクエストを送信するときにVAPID鍵の認証情報を使用できます。

3. 通知に対するPermissionの実装

実際にPush通知を送信する為に、ユーザーに許可を要請する必要があります。
そのためにはrequestPermissionメソッドを使用してユーザーに対する要請の結果をPromissで取得します。

App.vue
        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')
            })

この段階でローカル環境の画面にアクセスすると
PermissionのRequest.png
このような形で通知を表示のダイアログが確認できると思います。
またこの段階で許可をタップすると、ブラウザのコンソールにHave permissionと表示されることも確認できるでしょう。

次のステップに移る前にサービスワーカーファイルを作成しておきましょう。
ここではfirebase-messaging-sw.jsというファイル名で作成することが決まっているので、そのファイル名でファイルを作成したらドメインのルートに置きます。Laravelであれば、public/配下にファイルを設置します。今は作ったファイルは空でも構いません。

4. フォアグラウンド・バックグラウンドでの通知の受信

まず始めにFCMから発行されるトークンを取得します。先ほど書いたユーザーへの許可を要請した処理で、成功した時にトークンを取得するメソッドを呼び出すだけです。

App.vue
        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')
            })

ここまで書いて画面にアクセスするとトークンの取得が出来ていれば
getToken.png
このように表示されていると思います。
前述しましたが、こちらのFCMから発行されたトークンを使用して、対象の端末に通知を表示させます。

ここでPush通知が表示される際に2つのパターンがある事を認識しておく必要があります。

  • 1つ目はWebブラウザが閉じられていたり、ブラウザが閉じられていたりした場合は、3の通知に対するPermissionの実装の最後で作成したサービスワーカーファイル内でメッセージが受け取られます。
  • 2つ目はユーザーがWebページを表示している時です。この場合は実際のWebページ内でメッセージを受け取ります。なのでメッセージを受け取った際に何かのイベント(ラベルやマーカーの表示)を考えている場合は、メッセージを受け取るイベントで処理を書く必要があります。

それではメッセージを受け取るために、空で作成したサービスワーカーファイルにFirebaseメッセージングService Worker定義しましょう。
messagingSenderIdには上記のFirebaseを初期化した時に利用した値を指定してあげる形で大丈夫です。

firebase-messaging-sw.js
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イベントを呼び出して確認してみましょう。

App.vue
        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"

上記を実行すると
Foregrandメッセージ表示.png
こちらのように表示されていて、通知をWebページ内で受信している事が確認できると思います。

バックグラウンドでの受信

バックグラウンドで受信する際には、通知を受信するWebページにフォーカスがない状態をブラウザで作る(別タブで他のページを閲覧している)か、他のアプリにフォーカスが当たっている状態で先ほどのリクエストを投げると挙動が確認できると思います。

Backgroundでのメッセージ.png

確認できましたね。

今回は対象としませんが、通知オプションを設定したい場合(データペイロードを使用する場合など)はこちらを参照してください
基本的には、サービスワーカーファイルにメソッドを一つ追加して、データオプションに設定するだけです。

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を使用して、ユーザーになんらかのアクションを行う導線を実装したりしました。
無料で始められ手軽に実装できるので使う際の利点は多そうです。

13
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?