TheSabby TheSabby - 3 months ago 199
Javascript Question

How to use service worker with FCM for Push Notifications

I am trying to use service worker with Firebase to implement push notifications on chrome. I have a manifest file and an sw.js file in my web app. I have created a project in Firebase and I have tested registering and sending notifications. this all works fine except that when receiving the notifications the data is null. I don't understand why and there aren't any helpful resources (to my knowledge!).
Here is my service worker file:

self.addEventListener('push', function(event) {
console.log('Push message', event);
var title = 'Push message';
event.waitUntil(
self.registration.showNotification(title, {
body: 'The Message',
icon: 'images/logo.svg',
tag: 'my-tag'
}));
});


Here is my main.js file:

if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js').then(function(registration) {
// Registration was successful
console.log('ServiceWorker registration successful with scope: ', registration.scope);
registration.pushManager.subscribe({
userVisibleOnly: true
}).then(function(sub) {
console.log('endpoint:', sub.endpoint);
}).catch(function(e) {

});
}).catch(function(err) {
// registration failed :(
console.log('ServiceWorker registration failed: ', err);
});
}


Manifest.json:

{
"name": "APPNAME",
"gcm_sender_id": "SENDERID"
}


cURL Request:

curl --header "Authorization: key=APIKEY" -application/json" https://fcm.googleapis.com/fcm/send -d "{\"registration_ids\":[\"REGISTRATIONID\"],\"notification\":{\"title\":\"test\",\"body\":\"testing\"},\"data\":{\"title\":\"erse\"}}"


Console log of push event from sw.js:
enter image description here

I am not receiving any of the data I sent in the request. Is this done some other way with firebase?
Thanks in advance.

Answer

According to this, you can send data with chrome notification version for chrome version 50 onwards.

Prior to Chrome 50, push messages could not contain any payload data. When the ‘push’ event fired in your service worker, all you knew was that the server was trying to tell you something, but not what it might be. You then had to make a follow up request to the server and obtain the details of the notification to show, which might fail in poor network conditions.

Now in Chrome 50 (and in the current version of Firefox on desktop) you can send some arbitrary data along with the push so that the client can avoid making the extra request. However, with great power comes great responsibility, so all payload data must be encrypted.

For your current implementation you can do something like this:

self.addEventListener('push', function(event) {

var apiPath = '<apiPath>';
event.waitUntil(registration.pushManager.getSubscription().then(function (subscription){

    return fetch(apiPath).then(function(response){
        if(response.status !== 200){
            throw new Error();
        }

        return response.json().then(function(data){
            var title = data.title;
            var message = data.body;
            var icon = data.icon;
            var tag = data.tag;
            var url = data.url;
            return self.registration.showNotification(title,{
               body: message,
               icon: icon,
               tag: tag,
               data: url
            });
        })
    }).catch(function(err){

    })

}));
return;
});

For any specific notification which can be related to particular user, you can pass the parameter of registration id of the worker in api url and get the notification for that particular id. Hope this helps!