Firebaseを使ってWebプッシュ通知を送ってみた

## まえがき
「ブラウザにプッシュ通知を送ってみたいけど、実際やるとなるといろいろと手間がかかりそう・・・」
私もそんな悩みを持っていたのですが、Firebaseを使うことですごく簡単にWebプッシュ通知を実現することができました！ (※しかも無料！)　
今回はFirebaseのCloud Messagingサービスを使ってWebプッシュ通知を実装していきます！

## まずはじめに
簡単にこの記事で出てくる用語の説明をしておきます。

* Webプッシュ通知<br>ブラウザに対してプッシュ通知をする。
* Firebase<br>mBaaS(mobile backend as a Service)やBaasといわれており、バックエンド側のインフラを提供するサービス。Googleが提供。

* Firebase Cloud Messaging (以下、FCM)
Firebaseのサービスのひとつ。
プッシュ通知に関する様々な機能を提供しているサービスで、APIをたたくだけでいろいろとやってくれます。
 - プッシュメッセージ送信
 - トークンの管理
 - 送信者のグループ管理

* ServiceWorker
Webページのバックグラウンドで動く、独立したJavaScript環境。
プッシュ通知やオフライン対応などで使われる。

## 必須環境 
FCMを利用するのに必要な環境は以下の通り。
 
* 対応ブラウザ
 ・Chrome 50 以降
 ・Firefox 44 以降
 ・Opera Mobile 37 以降

* https環境
※オレオレ証明書だとダメ！

とりあえず試すなら、Firebase Hostingを使うと楽！
[Firebase Hosting](https://firebase.google.com/products/hosting/?hl=ja) (無料プランで利用可)

## 実際に作ってみる
以下の５つの処理を書くだけです！

 1. FCMを使うための設定
 2. ServiceWorkerを定義する
 3. 通知の受信許可を求める
 4. トークンを取得する
 5. メッセージを受信する

Firebaseの公式サイトでサンプルとチュートリアルが提供されているので、
そちらを利用すると簡単に試すことができます！
[公式サンプル](https://github.com/firebase/quickstart-js)

#### ファイル構成
実際に作るのはこの２ファイルです。

```
index.html               # Webページ
firebase-messaging-sw.js # ServiceWorker用スクリプト
```

#### ソースコード
以下のコードを埋め込むだけで通知を受け取ることができます！

```Javascript:index.html
<!-- Firebase SDK -->
<script src="https://www.gstatic.com/firebasejs/5.5.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.5.1/firebase-messaging.js"></script>
<script>
 /*  1. FCMを使うための設定 
  *  https://firebase.google.com/docs/cloud-messaging/js/client?authuser=0
  */
 var config = {
   messagingSenderId: "<作成したFirebaseプロジェクトのmessagingSenderIdを入れる>"
 };
 firebase.initializeApp(config);

 const messaging = firebase.messaging();

 // VAPIDを設定
 messaging.usePublicVapidKey('<作成したFirebaseプロジェクトのウェブプッシュ証明書-鍵ペアを入れる>');
 
 /* 2. ServiceWorkerを定義する */
 navigator.serviceWorker.register('./firebase-messaging-sw.js')
 .then((registration) => {
   messaging.useServiceWorker(registration);

   /* 3. 通知の受信許可を求める */
   messaging.requestPermission().then(function() {
     // 通知が許可されたときの処理を書く
   }).catch(function(err) {
     // 通知が拒否されたときの処理を書く
   });
 });

 // トークンが更新されているときのイベントハンドラ
 messaging.onTokenRefresh(function() {
   /*  4. トークンを取得する */
   messaging.getToken().then(function(refreshedToken) {
     // トークン取得後の処理を書く
   }).catch(function(err) {});
 });

 /* 5. メッセージを受信する */
 // ページがフォアグラウンドの時にメッセージを受信する用のイベントハンドラ
 messaging.onMessage(function(payload) {
   var notificationTitle = payload.notification.title; // タイトル
   var notificationOptions = {
     body: payload.notification.body, // 本文
     icon: payload.notification.icon, // アイコン
   };

  if (!("Notification" in window)) {
    // ブラウザが通知機能に対応しているかを判定
  } else if (Notification.permission === "granted") {
    // 通知許可されていたら通知する
    var notification = new Notification(notificationTitle,notificationOptions);
  }
});

```
```Javascript:firebase-messaging-sw.js
// 1. FCMを使うための設定を書く
importScripts('https://www.gstatic.com/firebasejs/5.5.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/5.5.1/firebase-messaging.js');

firebase.initializeApp({
  'messagingSenderId': 'XXXXXXXXXXX'
});

const message = firebase.messaging();

```
## メッセージを送信する
APIをPOSTリクエストでたたくと送信できます！

参考：[最初のメッセージを送信する](https://firebase.google.com/docs/cloud-messaging/js/first-message?hl=ja)

```:POSTリクエスト

POST https://fcm.googleapis.com/v1/projects/<作成したFirebaseプロジェクト名>/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer <作成したプロジェクトのサーバーキー>
{
  "message":{
    "token" : "<Webページで取得したトークン>",
    "notification" : {
      "title" : "タイトル",
      "body" : "メッセージ内容",
      }
   }
}
```
```:Curl
curl -X POST -H "Authorization: Bearer <作成したプロジェクトのサーバーキー>" -H "Content-Type: application/json" -d '{
"message":{
  "notification": {
    "title": "タイトル",
    "body": "メッセージ内容",
  },
  "token": "<Webページで取得したトークン>"
  }
}' "https://fcm.googleapis.com/v1/projects/<作成したプロジェクト名>/messages:send"
```

## まとめ
Firebaseを使うことで簡単にWebプッシュ通知を送ることができました！
しかし、ブラウザのサポート状況を見ても、まだまだこれからのサービスかなとも思います。。。

私自身も今回初めて触れて、知識もまだまだ浅いと思いますので、実際に運用して困ったことやノウハウ等ございましたら、ぜひコメントください！


## お知らせ
エイチームグループでは一緒に活躍してくれる優秀な人材を募集中です。
興味のある方はぜひとも[エイチームグループ採用ページ](https://www.a-tm.co.jp/recruit/)（[Webエンジニア詳細ページ](https://www.a-tm.co.jp/recruit/requirements/career/lifestylesupport-webengineer/)）よりお問い合わせ下さい！

## 最後に
明日は@Ingwardさんが「Windows10への移行時にやっておくといい事」を教えてくれるようです！
お楽しみに ♪