WebでもFCMが使えるようになったので、試してみたときの備忘録。
これでSafari以外には、通知が送れるようになる(´ω`)
使い方
構成は、@nuxtjs/pwaでPWA化している感じ。
コンソール側
Settingsでウェブプッシュ証明書を作成して、鍵ペアを取得する。

これを、PUBLIC_VAPID_KEYという環境変数に設定しておく。
クライアント側
firebaseの初期化
~/plugins/firebase.ts
というファイルを用意し、firebaseを初期化
// ~/plugins/firebase.ts
import * as firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
import "firebase/messaging";
if (!firebase.apps.length) {
// まずは、firebaseの初期化
firebase.initializeApp({
apiKey: process.env.API_KEY,
authDomain: process.env.AUTH_DOMAIN,
databaseURL: process.env.DATABASE_URL,
projectId: process.env.PROJECT_ID,
storageBucket: process.env.STORAGE_BUCKET,
messagingSenderId: process.env.MESSAGING_SENDER_ID,
appId: process.env.APP_ID,
measurementId: process.env.MEASUREMENT_ID
});
// Push通知をサポートしているかをチェック
// サポートしていないと、firebase.messaging()を呼んだときに例外が発生
const isSupported = firebase.messaging.isSupported();
// コンソールで発行した、ウェブプッシュ証明書の鍵ペアを取得
const publicVapidKey = process.env.PUBLIC_VAPID_KEY;
if (!!publicVapidKey && process.client && !!isSupported) {
// FCMの初期化。鍵ペアを設定する
const messaging = firebase.messaging();
messaging.usePublicVapidKey(publicVapidKey);
// @nuxtjs/pwaが生成するsw.jsと、
// 後で作成するFCM受信処理用のsw-firebase-messaging.jsを統合するための設定
navigator.serviceWorker
.register("/sw.js")
.then(registration => messaging.useServiceWorker(registration))
.catch(err => console.error(err));
}
}
export default firebase;
トークンの取得
Push通知を送る際の宛先として、トークンを指定しないといけないので取得。
トークンは端末ごとに取得する必要があるので、注意が必要。
※PCとスマホだとそれぞれトークンが違う
import firebase from "~/plugins/firebase";
// トークンの取得
public async getToken(user: User) {
const isSupported = firebase.messaging.isSupported();
if (!isSupported) return;
const token = await firebase.messaging().getToken();
// firestoreにトークンを保存しておく処理(中身は略)
await saveToken(user, token);
}
Firestoreなどへユーザごとにトークンを保存しておく。
firebase.messaging().getToken();
を呼んだ際に、
通知の設定が「確認」だと、許可を求めるダイアログが表示される。
これが許可されていないと、トークンも取得できない。
メッセージを受け取ったときの処理
メッセージを受信したときに受け取る関数は2つあり、
- フォアグラウンド(画面を見ている時) ... onMessage
- バックグラウンド(画面を見ていない時) ... setBackgroundMessageHandler
・【参考】JavaScript クライアントでメッセージを受信する | Firebase
今回はバックグラウンドのときに通知を送りたいので、
setBackgroundMessageHandler
を設定していく。
こんな感じ。
ドキュメントを見ると、『firebase-messaging-sw.js
というファイル名で作成』と書かれているけど、
その名前にすると、自動で読み込まれてしまう。。
開発用と本番用で切り替えたいときなどもあるので、@nuxtjs/pwaが生成するsw.jsと統合できるように、
sw-firebase-messaging.js
という名前でファイルを作成しておく。
ファイル名を変更したので、上で書いている「firebaseの初期化」の部分で、
messaging.useServiceWorker(registration)
を呼んでいる形。
// ~/static/sw-firebase-messaging.js
importScripts("https://www.gstatic.com/firebasejs/7.14.2/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/7.14.2/firebase-messaging.js");
// Firebaseの初期化
firebase.initializeApp({
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
measurementId: "...",
});
// [START background_handler]
const isSupported = firebase.messaging.isSupported();
if (!!isSupported) {
const messaging = firebase.messaging();
// バックグラウンド時の処理
messaging.setBackgroundMessageHandler(function(payload) {
// 受け取ったFCMの内容を取得
const notificationTitle = payload.notification.title;
const notificationOptions = {
body: payload.notification.body,
icon: payload.notification.icon,
};
// 通知を作成する
return self.registration.showNotification(notificationTitle, notificationOptions);
});
}
// [END background_handler]
nuxt.config.tsでPWA関連の設定をする
作成したsw-firebase-messaging.js
を取り込む設定と、
@nuxtjs/pwaが生成するmanifest.jsonに、gcm_sender_idを追加する設定を追加
import { Configuration } from "@nuxt/types";
const config: Configuration = {
// 略
modules: [
"@nuxtjs/pwa",
],
workbox: {
// sw-firebase-messaging.jsをimportするように追加
importScripts: [
"sw-firebase-messaging.js"
]
},
pwa: {
manifest: {
// manifest.jsonにgcm_sender_idを追加
gcm_sender_id: process.env.MESSAGING_SENDER_ID || ""
}
},
};
export default config;
これでクライアント側はOK!
サーバ側: メッセージを送信する
メッセージの送信は、firebase-adminでできる。
・アプリサーバーからの送信リクエストを作成する | Firebase
firestoreを利用しているので、Cloud Functionsのfirestoreトリガーを使い、
ドキュメントが追加されたら通知するようにしている例。
import * as functions from "firebase-functions";
import admin from "../common/firebaseAdmin"; // 初期化済みのfirebase-admin
export default functions
.firestore.document("ドキュメントのパス")
.onCreate(async (snap, context) => {
// getTokenで保存しておいたトークンを取得(中身は略)
const token = getToken();
// 通知の送信
const title = "通知するタイトル";
const body = "通知する本文";
const icon = "通知で表示するアイコン画像のURL"
const link = "通知をタップしたときに開くURL"
await admin.messaging().send({
// 送信先の端末のトークン
token: token,
// 通知する内容
notification: {
title: title,
body: body
},
// Web Push向けの通知内容
webpush: {
notification: {
icon: icon
},
fcmOptions: {
link: link
}
}
});
});
送信はこれだけ!
ほかの小ネタ
トークンを削除する
firebase.messaging().deleteToken();
でトークンを無効化できる。
// トークンの削除
public async deleteToken(user: User) {
const isSupported = firebase.messaging.isSupported();
if (isSupported) {
const token = await firebase.messaging().getToken();
await firebase.messaging().deleteToken(token);
}
}
フォアグラウンドで通知を受け取ったときになにかする
onMessage
を使うと、通知を受け取ったときに呼び出してくれる。
firebase.messaging().onMessage(async (payload) => {
// 受け取ったときの処理
});
トークンが変更されたときになにかする
onTokenRefresh
を使うと、トークンが更新されたときに呼び出してくれる。
新しいトークンは再度getToken()
を呼ばないといけない。
firebase.messaging().onTokenRefresh(async () => {
// トークンが更新されたときの処理
});
通知の許可状態を確認する
通知の状態は、Notification.permission
で確認できるらしい。
・Notification.permission - Web API | MDN
if (Notification.permission === "default") {
// 確認(デフォルト)
} else if (Notification.permission === "granted") {
// 許可
} else if (Notification.permission === "denied") {
// 拒否
}
【PR】これをつかって、こんなのつくりました!
1週間でWebサービスを作るイベント web1weekへの投稿作品です!
よかったら、遊んでみてください(´ω`)
■エアで投げ銭できるWebサービス「エア銭」
URL: https://air-money.netlify.app/
参考にしたサイトさま
- FRESH! における Web プッシュ通知機能 〜実装編〜 | CyberAgent Developers Blog
- quickstart-js/firebase-messaging-sw.js at bcce38ebc1e5602560e2b76b20f19b7834b8279e · firebase/quickstart-js
- Messaging | JavaScript SDK | Firebase
- 複数のデバイスにメッセージを送信する | Firebase
- REST Resource: projects.messages | Firebase
- アプリサーバーからの送信リクエストを作成する | Firebase
- バックグラウンド アプリにテスト メッセージを送信する | Firebase
- JavaScript Firebase Cloud Messaging クライアント アプリを設定する
- Firebase Cloud Messagingで始めるWebプッシュ通知 - Qiita