Help us understand the problem. What is going on with this article?

vue.js&PWAにwebプッシュ通知を適用させてみた

More than 1 year has passed since last update.

はじめに

firebase&PWAでのpush通知のサンプルはよく見かけたのですが、
vue-cliで作ったプロジェクトにpush通知を適用するサンプルはなかなか見つからなかったので試行錯誤してみました。
webpackの知識が浅いので、もっと良いやり方あるで!って人はぜひ教えてください。
pushサーバーを作るのは大変そうなので、今回はfirebaseを利用しました。

なお、この記事ではpush通知やらfirebaseやらの細かい仕様は解説しません。

必要なもの

vue-cli(node,npmなども)
firebaseのアカウント

ひな形プロジェクト作成

こちらの記事を参考に作成しました。
最近vue-cli 3がリリースされましたが、今回は2系で作成しました。
なおリンク先では 3.Vue.jsのSPAをPWA化する という手順を踏んでいますが、今回はやりません。

出来上がったプロジェクトをnpm run buildすると、distフォルダの中にservice-worker.jsが出来上がっているのが分かります。
このservice-worker.jsにwebpush通知の記述をすればpush通知が動くはずなのですが、
デフォルトだとpush通知の記載がないのでどうにかしてpush通知のコードをこのjsファイルに追記しなければなりません。
build結果のjsに対して直接記述するのはアレなので、設定ファイルを多少いじって工夫します。

push通知の記述をbuild結果のserviceworkerにマージする

自前のサービスワーカーを用意

src内のstaticフォルダ内にjsファイルを追加します。
ファイル名はなんでもいいのですが、今回はmysw.jsとします。

mysw.js
self.addEventListener("push", function(event) {
    event.waitUntil(
      self.registration.pushManager.getSubscription()
        .then(function(subscription) {
          if (subscription) {
            return subscription.endpoint
          }
          throw new Error('User not subscribed')
      })
      .then(function(res) {

        return self.registration.showNotification('title', {
          body: 'contents'
        })
      })
    )
})

self.registration.showNotificationの引数はアイコン、タグなど色々ありますが今回は省略します。

設定ファイルをいじる

ここでいじるのはwebpack.prod.conf.jsです。
SWPrecacheWebpackPluginの部分の記載を下記のように修正します。

webpack.prod.conf.js
// service worker caching
    new SWPrecacheWebpackPlugin({
      cacheId: 'your-project',
      filename: 'service-worker.js',
      staticFileGlobs: ['dist/**/*.{js,html,css}'],
      minify: true,
      stripPrefix: 'dist/',
      importScripts: ['./static/mysw.js']//この行を追加
    })

これによって、デフォルトで出来上がるservice-worker.jsに、自分が書いたmysw.jsがマージされます。
どうなっているか気になる方は、再度npm run buildした後のservice-worker.jsファイルの中を確認してみてください。

ここまでで半分くらいです。続いてはfirebaseと連携する処理を記述していきます。

firebaseと連携

firebaseのプロジェクト作成

とりあえずfirebaseであたらしいprojectを作ってみましょう。
firebaseにログインして新しいプロジェクトを追加しましょう。
プロジェクトを追加したら、プロジェクトの設定>クラウド メッセージングタブ内の、
・サーバーキー
・送信者ID
をメモってください。

ここで作成したプロジェクトがpushサーバーの役割を担います。

ソースコード修正

manifest.json,service-worker-prod.jsを修正します。

manifest.json
"gcm_sender_id":"送信者ID"//ファイルの最後に←のコードを追加(先ほどメモった送信者IDをここに書く)

service-worker-prod.jsについてはwindow.addEventListener('load', function()以下を下記の通り修正

service-worker-prod.js
    window.addEventListener('load', function() {
      if ('serviceWorker' in navigator) {
        navigator.serviceWorker.register("service-worker.js");
        navigator.serviceWorker.ready.then(function(registration) {
            return registration.pushManager.getSubscription().then(function(subscription) {
              if (subscription) {
                return subscription;
              }
              return registration.pushManager.subscribe({
                userVisibleOnly: true
              })
            })
        }).then(function(subscription) {
            console.log("pushManager endpoint:", subscription.endpoint) 
        }).catch(function(error) {
            console.warn("serviceWorker error:", error)
        })
      }
    });

push通知を許可するようにソースを修正しています。
また、subscriptionのendpointをconsole.log出力している処理がありますが、
最後のpush通知に重要な情報を吐き出しています。

ここまでやったらpush通知の準備完了です。

push通知を試してみる

資源をhttps対応のサーバーに配置

私はお手軽なgithubPagesを利用しています。
npm run buildで吐き出されるdist配下の資源をまるっとgithubにpushしてgithubPagesの設定をしてください。
あまり自分はFirebase詳しくないのですが、firebaseは静的資源のホスティングサービスあるみたいなので、そっちでもいいかもです。

ページにアクセス

ディベロッパーツールを開きながら、該当ページにアクセスしてください。
うまくいっていたらコンソールログに
pushManager endpoint: https://android.googleapis.com/gcm/send/*endpointの値*
が出力されているはずです。
このendpointの値は最後のpush通知に必要な値なのでメモってください。

curlコマンドでpush通知

下記コマンドを叩くとwebにpush通知が届くはずです。

curl "https://fcm.googleapis.com/fcm/send" \
     -X POST \
     -H "Content-Type: application/json" \
     -H "Authorization: key=サーバーキー" \
     -d '{
          "notification": {
            "title": "タイトル",
            "body": "本文",
            "click_action": "http://example.com"
          },
          "to": "endpointの値"
        }'

今回は簡単のためにcurlコマンドを利用していますが、rest系のクライアントツール、Ajaxでも同様に動きます。

参考URL

https://qiita.com/gyarasu/items/2f18edc4ae251180d89e
https://qiita.com/keki/items/81634135586763de235a
https://qiita.com/srai0628/items/ebd417b7877295031718

catDaisuke
ユーザー系子会社エンジニア。 興味 node.js vue.js java AWS
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away