javascriptvue.jsfirebase-cloud-messagingnuxt.jsservice-worker

Can't catch FCM 'notificationclick' event in service worker using firebase messaging with Nuxt.js and Vue.js


Having trouble seeing any events other than install, activate, or push in my firebase-messaging-sw.js. Notifications are being received and served, but I am unable to see the event handler for notificationclick. When I receive a notification from firebase and is clicked on I fail to see the notificationclick event take place in the service worker logs.

I am using @nuxtjs/firebase 8.2.2 and have followed the setup from the guide: https://firebase.nuxtjs.org/service-options/messaging.html.

In firebase-messaging-sw.js

self.addEventListener('notificationclick', function (event) {
  console.log('Notification click');
  event.notification.close();
  const url = 'home';
  event.waitUntil(
    self.clients.matchAll({ type: 'window' }).then((windowClients) => {
      // Check if there is already a window/tab open with the target URL
      for (let i = 0; i < windowClients.length; i++) {
        const client = windowClients[i];
        // If so, just focus it.
        if (client.url === url && 'focus' in client) {
          console.log('focusing..');
          return client.focus();
        }
      }
      if (self.clients.openWindow) {
        console.log('open window');
      }
    })
  );
}, false);

I am also trying to use postMessage() to our service worker on a separate page to inject the users email to the service worker:

In account.vue

    navigator.serviceWorker.ready.then((sw) => {
      console.log('Requesting permission. Service worker: ', sw);
      Notification.requestPermission().then(async (permission) => {
        let token = null;
        if (permission === 'granted') {
          console.log('Notification permission granted.');
          await sw.active.postMessage({ action: 'saveEmail', email: this.email });
        }
      });
    });

In firebase-messaging-sw.js

self.addEventListener('message', async (msg) => {
  console.log('message', msg);
  const clients = await self.clients.matchAll({ type: 'window' });
  for (const client of clients) {
    client.postMessage(msg);
  }

  if (msg.data.action === 'saveEmail') {
    USER_EMAIL = msg.data.email;
  }
});

TLDR; I am having trouble seeing notificationclick events happen in my firebase-messaging-sw.js.

EDIT: I added the push event handler which is being hit, but I am still unable to catch the notificationclick event


Solution

  • So I found this bit from the importScripts I'm using in the firebase-messaging-sw.js:

    export async function onNotificationClick(
      event: NotificationEvent
    ): Promise<void> {
      const internalPayload: MessagePayloadInternal =
        event.notification?.data?.[FCM_MSG];
    
      if (!internalPayload) {
        return;
      } else if (event.action) {
        // User clicked on an action button. This will allow developers to act on action button clicks
        // by using a custom onNotificationClick listener that they define.
        return;
      }
    
      // Prevent other listeners from receiving the event
      event.stopImmediatePropagation();
      event.notification.close();
    

    Specifically the event.stopImmediatePropagation(); was keeping my own notificationclick listener from receiving the event. This is fixed by putting my own notificationclick listener above the importScripts.

    In regards to the postMessage, that was failing due to communicating with another running service worker. I used the getRegistrations() to specify which service worker to communicate with.

     navigator.serviceWorker.getRegistration('service-worker-scope-url').then((registration) => {
          console.log('we found our sw!');
          if (registration) {
            registration.active.postMessage({ action: 'saveEmail', email: this.$auth.user.email });
          }
        });