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 :
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
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.