Nuxt.js + Firebase Cloud Messagingを使ってWeb pushをしてみた（導入編）

# 概要
今回のNuxt.js #2 Advent Calendar 2018ではNuxt.jsとFirebaseが提供しているCloud Messagingを使ってWeb push機能を実装してみたことについて書こうと思っています。
この記事では導入編なので、firebaseで発行したtokenを取得して、curlを使ってweb pushをするところまで書きます。

実際にフォームを作って、ボタンを押したらpush通知が飛ぶようにするのは自分が所属しているAdvent Calendarで書こうと思っているので、あらかじめご了承ください。
また、この記事ではCloud Messagingの説明などは省こうと思っていますので、Cloud Messagingが何なのか知りたい方は公式のドキュメントを参照ください。

#### 実装環境
- node v8.14.0
- nuxt.js 2.0.0
- firebase 5.7.0

# 実装方法
### ウェブ認証情報の設定
FCM のウェブ インターフェースでは、Voluntary Application Server Identification 鍵（VAPID 鍵）」と呼ばれるウェブ認証情報を利用して、サポートされているウェブプッシュサービスへの送信要求が承認されます。そのため、アプリをプッシュ通知に登録するには、鍵ペアをFirebaseプロジェクトに関連付ける必要があります。

まず設定画面にて
<img width="781" alt="スクリーンショット 2018-12-09 17.00.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/271450/ea0754c3-553d-0e5c-1888-c3a523c1f46d.png">
タブのメニューにある`クラウドメッセージング`のタブをクリックします。

そしたら一番下に
<img width="967" alt="スクリーンショット 2018-12-09 17.05.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/271450/e2f95642-5b90-b9e0-2ff0-dd2d12711f46.png">

ウェブプッシュの証明書を発行するセクションがあるので、鍵ペアを生成をクリックして証明書を発行してください
こちらは後ほどコードの説明で使用します。

### Firebase周りの設定
まずはじめにFirebaseをinstallします。

```bash
$ yarn add global firebase
```

Firebaseのinstallが終わりましたら、pluginディレクトリにFirebaseのコンソールに書いてあるscriptを書きます。
scriptはFirebaseのコンソールトップから赤枠で囲った部分をクリックします。
![Group.png](https://qiita-image-store.s3.amazonaws.com/0/271450/0ef97233-22e3-272f-a834-6ece7f01ddce.png)
そしたらmodalが表示されるので
![modal.png](https://qiita-image-store.s3.amazonaws.com/0/271450/800a9652-5886-6f05-b48b-f330607dc906.png)
そちらに掲載されているコードをpluginディレクトリにfirebase.jsを作成し、下記のコードに記入します。

```~/plugins/firebase.js
import firebase from 'firebase'

if (!firebase.apps.length) {
  firebase.initializeApp({
    apiKey: '',
    authDomain: '',
    databaseURL: '',
    projectId: '',
    storageBucket: '',
    messagingSenderId: ''
  })
}

export default firebase
```

これでFirebaseのscriptの設定は完了です。

### メッセージを受信するように設定する
nuxt.config.jsに以下の項目を追加してください。
この項目がないとメッセージが受信できません。

```nuxt.config.js
manifest: {
  gcm_sender_id: '103953800507'
}
```
また、値はすべて固定なので変更しないように注意してください。

### プッシュ通知の処理
主な処理は以下のようなコードです。

```js
const messaging = firebase.messaging()
messaging.usePublicVapidKey('PUBLIC KEY')
messaging.requestPermission().then(function() {
  messaging.getToken().then(function(currentToken) {
    if (currentToken) {
      sendTokenToServer(currentToken)
      updateUIForPushEnabled(currentToken)
    } else {
      // Show permission request.
      console.log('No Instance ID token available. Request permission to generate one.')
      // Show permission UI.
      updateUIForPushPermissionRequired()
      setTokenSentToServer(false)
    }
  })
  .catch(function(err) {
    console.log('not', err)
  })
})
.catch(function(err) {
  console.log('Unable to get permission to notify.', err)
})
```

どこがどのような処理をするのかかいつまんで説明しようと思います。

#### メッセージングオブジェクトの取得
メッセージングオブジェクトは

```js
const messaging = firebase.messaging()
```
で取得されます。

#### ウェブ認証情報の設定
ウェブ認証の設定は

```js
messaging.usePublicVapidKey('PUBLIC KEY')
```
で処理されます。
usePublicVapidKey()メソッドを使用すると、FCM で各種プッシュ サービスにメッセージ要求を送信するときに VAPID 鍵の認証情報を使用できます。
PUBLIC KEYは[ウェブ認証情報の設定](#ウェブ認証情報の設定)で発行したpublic keyを記入します。

#### 通知の受信許可
通知の受信許可は

```js
messaging.requestPermission().then(function() {
  console.log('success')
　　　　...
})
.catch(function(err) {
  console.log('Unable to get permission to notify.', err)
})
```
で処理されます。
messaging.requestPermission()メソッド は、ブラウザでアプリが通知を受け取れるようにするかどうか、ユーザーに許可を求める同意ダイアログを表示します。

<img width="348" alt="スクリーンショット 2018-12-09 17.50.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/271450/168fcbd8-bdb4-6f57-f245-abfea6e00d58.png">
皆さんもみたことがあるようなこれです。

許可を押した場合はsuccessされ、ブロックを押した場合は.catchで処理されます。

#### 登録トークンにアクセス
現在の登録トークンの取得は

```js
messaging.getToken().then(function(currentToken) {
  console.log('success')
})
.catch(function(err) {
  console.log('not', err)
})
```
で処理されます。
getToken()メソッドで現在の登録されているtokenを取得します。
まだ権限が付与されていない場合、このメソッドは null を返します。そうでない場合は、トークンを返すか、エラーが原因で Promise を拒否します。

tokenをモニタリングする場合`onTokenRefresh()`メソッドを使用します。
トークンは初期起動後にローテーションされている可能性があるため、トークン更新をモニタリングして、更新された最新の登録トークンを常に取得する必要があるため、`onTokenRefresh()`を使用してそのコンテキストで`getToken`を呼び出すと、利用可能な最新の登録トークンに確実にアクセスできます。

#### pushしてみる
実際にpush通知してみます。
rootディレクトリにjsonファイルを作成して、その中でメッセージ内容などの定義をした方が楽なので、今回はそのようにします。

```push.json
{
  "to": "TOKEN",
  "time_to_live": 60,
  "notification": {
      "title": "title",
      "body": "body",
      "icon": "icon",
      "click_action": "url"
  }
}
```

ここでは通知の項目などを設定してます。

toの部分では[前のセクション](#登録トークンにアクセス)で説明したtokenの取得で、取得したtokenを使用します。

pushのcurlコマンドです。

```bash
curl -H "Authorization: key=SERVER-KEY" \
       -H "Content-Type: application/json" \
       -X POST "https://fcm.googleapis.com/fcm/send" -d @push.json
```
SERVER-KEYはFirebaseのコンソールの設定画面から、タブのメニューにある`クラウドメッセージング`のタブをクリックした一番上のセクションに書いてあるサーバーキーを使用します。
![auth.png](https://qiita-image-store.s3.amazonaws.com/0/271450/ca34f9b5-3275-e032-1571-882efb502f5a.png)

成功すると実際にこのような通知が飛んできます。
<img width="384" alt="スクリーンショット 2018-12-09 17.24.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/271450/0db7e0d4-3f87-af78-19b3-c4c05b10ae8a.png">



# まとめ
Cloud Messagingを使って実際にWeb pushを実行してみましたが、firebaseからのtoken取得で結構つまずいてしまったの導入にすこし手こずってしまった部分がありました。
ですが、文言の内容やpushの際に表示される画像も変更可能なので、実務的にも導入すればかなり便利な機能なのでみなさんもぜひ試してみてください。

実践編は自分が所属しているAdvent Calendarで書く予定なのでぜひそちらもご覧ください。