Search code examples
reactjsfirefoxfirebase-cloud-messagingprogressive-web-appsvite

Firebase messaging (FCM) with Vite PWA works with Chrome but not with Firefox


I'm trying to setup push notifications with firebase messaging (FCM) for a React-Vite PWA application. Following the docs of Vite and a solution provided by a stackoverflow user ( https://stackoverflow.com/a/76283695/17420705 ). I managed to override the default service worker provided by Vite and register the firebase messaging service worker.

When I test the notifications from the firebase console, it works perfectly with Chrome, Edge, Opera but not with Firefox. I have the following error inside the firefox web console : enter image description here

It throws an exception during the script evaluation which means that Firefox can't read correctly the service worker file if I am not mistaken ?

This is how my Vite config file looks like :

import { VitePWA } from 'vite-plugin-pwa'
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig(({command, mode}) => {
// for firebase settings, the solution was found here :  https://stackoverflow.com/a/76283695/17420705
  return { plugins: [react(), VitePWA({
    strategies: 'injectManifest', 
    injectRegister: null, 
    registerType: 'autoUpdate',
    srcDir: 'dev-dist', 
    filename: 'sw.js', 
   devOptions: {
     enabled: true,
     type: 'module', //firebase
     navigateFallback: 'index.html' //firebase
   },
   workbox: { //firebase
    sourcemap: true
  }
   })],
 server: {
   port: 3000
 },
 build: {
   outDir: mode === 'qa' ? 'dist-qa' : 'dist'
 }}
})

Based on the Vite docs related to the injectManifest strategy of Vite (https://vite-pwa-org.netlify.app/guide/development.html#injectmanifest-strategy), it's written that

You can use type: 'module' when registering the service worker (right now only supported on latest versions of Chromium based browsers: Chromium/Chrome/Edge)

WARNING When building the application, the vite-plugin-pwa plugin will always register your service worker with type: 'classic' for compatibility with all browsers.

When using this strategy, the vite-plugin-pwa plugin will delegate the service worker compilation to Vite, so if you're using import statements instead importScripts in your custom service worker, you must configure type: 'module' on development options.

Does it mean that the import statements of my service worker file are not recognized by Firefox because it doesn't support modules contrary to chromium based browsers ? Here's my service worker file :

import { NavigationRoute, registerRoute } from 'workbox-routing';
import { cleanupOutdatedCaches, createHandlerBoundToURL, precacheAndRoute } from 'workbox-precaching';
import { getMessaging, onBackgroundMessage } from "firebase/messaging/sw";

import { clientsClaim } from 'workbox-core';
import { initializeApp } from "firebase/app";

console.log("starting to install sw");
// self.__WB_MANIFEST is default injection point
precacheAndRoute(self.__WB_MANIFEST);

// clean old assets
cleanupOutdatedCaches();

let allowlist;
if (import.meta.env.DEV) {
  allowlist = [/^\/$/];
}

// to allow work offline
registerRoute(new NavigationRoute(
  createHandlerBoundToURL('index.html'),
  { allowlist },
));

// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = initializeApp ({
 
});


const messaging = getMessaging(firebaseConfig);
onBackgroundMessage(messaging, (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'
  };

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

self.skipWaiting();
clientsClaim();

I have tried to replace the import module with importScripts but I didn't get any results. Here's my firebase file where I register the service worker :

// Import the functions you need from the SDKs you need

import { getMessaging, getToken, onMessage } from 'firebase/messaging'

import { getAnalytics } from "firebase/analytics";
import { initializeApp } from "firebase/app";

// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries

// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = initializeApp ({
});

console.log('*** Firebase Config ***', firebaseConfig)

const messaging = getMessaging(firebaseConfig);
console.log(messaging);

export const getOrRegisterServiceWorker = () => {
   if ('serviceWorker' in navigator) {
    console.log(import.meta.env.MODE);
    return window.navigator.serviceWorker
      .getRegistration('/firebase-push-notification-scope')
      .then((serviceWorker) => {
        if (serviceWorker){
          console.log("service worker exists");
          return serviceWorker;
        } 
        console.log("service worker is gonna be register");
        return window.navigator.serviceWorker.register(import.meta.env.MODE === 'production' ? '/sw.js' : '/dev-sw.js?dev-sw',
        { type: import.meta.env.MODE === 'production' ? 'classic' : 'module' })
        .then((serviceWorker)=>{
              console.log("success registering SW");
        }).catch((err)=>{
          console.log("registering failed",err);
        });
        // { type:  'module' });
      }
  )}
  throw new Error('The browser doesn`t support service worker.');
};

export const getFirebaseToken = () =>
  getOrRegisterServiceWorker()
    .then((serviceWorkerRegistration) => 
      getToken(messaging, { vapidKey: vapidKEY, serviceWorkerRegistration }));



export const onForegroundMessage = () => 
  new Promise((resolve) => {
    onMessage(messaging, (payload) => {
      resolve(payload);
  });
});

Did anyone face the same issue with Firefox and Vite PWA for firebase messaging and found a solution ?

Thank you


Solution

  • Small update: Firebase messaging FCM works with Firefox when the app is deployed so if it works locally with Chrome based browsers, it will work once your app is deployed.