'The web app showing "This website has been updated in the background"

The message can be received in background well, but the people in the foregrround will nit receive the message and just show "This website has been updated in the background".

I used the code sample from the fcm documentation.

Index.html (skipped the init script)

messaging.onMessage(function(payload) {
   console.log('Message received. ', payload);
   notificationTitle = payload.data.title;
   notificationOptions = {
     body: payload.data.body,
     icon: payload.data.icon
   };

   var notification = new Notification(notificationTitle,notificationOptions); });

sw.js

messaging.setBackgroundMessageHandler(function(payload) {

  const notificationTitle = payload.data.title;
  const notificationOptions = {
    body: payload.data.body,
    icon: payload.data.icon,
    badge: payload.data.badge
  };

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

Can anyone help? THX!



Solution 1:[1]

If you want to display messages from the service worker in your app, use the following.

In your sw.js, this is how you talk to your users/app instances:

self.clients.matchAll().then(function(clients) {
    clients.forEach(function(client) {
        client.postMessage({
            msg: "cached: " + event.request.url
        });
    });
});   

Then in your index.html script, this is how you process the message:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
        navigator.serviceWorker.register('/service-worker.js').then(function(registration) {
            console.log('ServiceWorker registration successful with scope: ', registration.scope);
        }, function(err) {
            console.log('ServiceWorker registration failed: ', err);
        });
    });
}
navigator.serviceWorker.addEventListener('message', function(event) {
  console.log("service worker " + event.data.msg);
  //you can do whatever you want now that you have this data in script.
});

Solution 2:[2]

The topic is pretty old, but I'll leave my solution here in case someone would have this issue.

The explanation of this issue can be found in this article https://developers.google.com/web/fundamentals/push-notifications/handling-messages#wait_until

In a nutshell push event shouldn't get executed before the promise created by ?self.registration.showNotification is resolved.

Using onBackgroundMessage the way official fcm docs offers reveals the same problem. To understand why we can look at declaration of onPush function in sw-listeners.ts and how this function is actually called in register.ts file. You can see that onPush is passed to e.waitUntil which means that push event doesn't get resolved before the promise returned by onPush:

self.addEventListener('push', e => {
    e.waitUntil(onPush(e, messaging as MessagingService));
});

however, when you look at how onBackgroundMessageHandler is called inside onPush, you'll see that the call doesn't return promise or something.

Solution I came to is like this:

self.addEventListener('push', function (event) {
    event.waitUntil(
        self.clients
            .matchAll({type: 'window', includeUncontrolled: true})
            .then(windowClients => {
                let visibleClients = windowClients.some(client => client.visibilityState === 'visible' &&
                    // Ignore chrome-extension clients as that matches the background pages of extensions, which
                    // are always considered visible for some reason.
                    !client.url.startsWith('chrome-extension://'));

                if (!visibleClients) {
                    event.waitUntil(
                        self.registration.showNotification(data.data.title)
                    );
                }
            })
    );
});

Checking clients for visibility provides handling for background messages only; this check is taken from onPush function of the library.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ronnie Royston
Solution 2