:::: MENU ::::

firebase-messaging.js を使ってハマったポイント3点

Firebase をいくらか使ってみて感じた、みんなもハマりそうなポイントをメモしておく。

setBackgroundMessageHandler が発火しない

ソースだけ見ていると、payload にサーバーからプッシュで送りたいデータが入っていて、 showNotification で表示させる前にカスタマイズできるところだなと思うのだが、
ここの仕様はちょっと複雑。

messaging.setBackgroundMessageHandler(function(payload) {
console.log(
"[firebase-messaging-sw.js] Received background message ",
payload
);
// Customize notification here
const notificationTitle = "Background Message Title";
const notificationOptions = {
body: "Background Message body.",
icon: "/firebase-logo.png"
};

return self.registration.showNotification(
notificationTitle,
notificationOptions
);
});

setBackgroundMessageHandler never fired · Issue #71 · firebase/quickstart-js
Github の issue に発火しないぞと投稿があるように、
マニュアル通り使っていると setBackgroundMessageHandler が発火することはまずない。

# setBackgroundMessageHandler が発火しない
{
"notification": {
"title": "Background New Topic Title",
"body": "Background New Topic body",
"click_action": "https://firebase.google.com/"
},
"data": {
"id": "hogehoge",
"age": 30
},
"to": "[YOUR-REGISTRATION-ID]"
}

# setBackgroundMessageHandler が発火する
{
"data": {
"title": "Background New Topic Title",
"body": "Background New Topic body",
"click_action": "https://firebase.google.com/",
"id": "hogehoge",
"age": 30
},
"to": "[YOUR-REGISTRATION-ID]"
}

notification フィールドを使ってプッシュ通知で出したい要素を指定していると、setBackgroundMessageHandler を無視して通知が出る仕組みらしい。

解決策

notification フィールドを使わずにすべて data フィールドに入れておくと、setBackgroundMessageHandler が発火される!

Note: If you set notification fields in your HTTP or XMPP send request, those values take precedence over any values specified in the service worker.
(Receive Messages in a JavaScript Client  |  Firebase)

サーバーから送った値が優先されるのは知っていたが、
setBackgroundMessageHandler 自体が発火されないとは思わなかった。

自前の notificationclick の function が発火しない

notificationclose fired but notificationclick dose not fire · Issue #102 · firebase/quickstart-js
どうにもわからねぇとなって issue まで発行してしまったのだが、
firebase-messaging.js を読み返してたら自己解決した。

importScripts("https://www.gstatic.com/firebasejs/3.5.2/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/3.5.2/firebase-messaging.js");

firebase.initializeApp({
messagingSenderId: "xxxxx"
});
const messaging = firebase.messaging();

// not fire
self.addEventListener("notificationclick", function(event) {
console.log("notification open");
// log send to server
});

// fired
self.addEventListener("notificationclose", function(event) {
console.log("notification close");
// log send to server
});

初めはこんな感じで書いていたのだが、
notificationclone は反応するのに notificationclick が反応しない!!

firebase-messaging.js の中を見ると、
同じく notificatoinclick を呼んでいるがこちらは起動している。

      T.addEventListener("notificationclick", function (a) {
return ga(b, a)
}, !1);

addEventListener で add って言うくらいだから、
同じ element に対して同じ event type でいけるはずなのになぜ?

もうちょっと読み進めていくと怪しいメソッドを見つける。
(他にも notification.close で element を閉じてしまっているから後続の同 element を使う処理が動いていないのでは?と思ったが検討違いだった)

    ga = function (a, b) {
if (b.notification && b.notification.data && b.notification.data.FCM_MSG) {
b.stopImmediatePropagation();
b.notification.close();

Event.stopImmediatePropagation() - Web APIs | MDN

stopImmediatePropagation どうやら多重実行防止のための関数らしい。
これ以降は addEventListener をしていても同じ element と event type のものは実行されない。

解決策

stopImmediatePropagation される前に addEventListener してしまえば、
先に実行されるので、これで自前の notificationclick が発火するようになった!

self.addEventListener("notificationclick", function(event) {
console.log('notification open');
var message = event.notification.data.FCM_MSG;
console.log(message);
// log send to server
});

importScripts('https://www.gstatic.com/firebasejs/3.5.2/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.5.2/firebase-messaging.js');

firebase.initializeApp({
'messagingSenderId': 'xxxxx'
});
const messaging = firebase.messaging();

日本語版のドキュメントは記述が古い

FCM の左メニューを見てもらえれば一目瞭然なのだが、
Web と FCM サーバーだけでもだいぶ違う。

そもそも大項目の時点で Unity とか日本語版はないし。
これのせいで 1 回古い仕様や非推奨の要素使って実装してしまった……

解決策

他の部分も情報が古い&情報自体がないことがあるので、
横着せずに英語版のドキュメントを読みましょう。