I am working on Firebase Cloud Messaging on React Js. My project works if I keep my service worker inside the public folder. However, it is not ideal to initialize Firebase Config in the public folder since the data would be easily accessible to anyone. Furthermore, the Firebase Config needs to be different for production and local/development environment, this is not possible if I keep it hard coded.
How should I initialize the Firebase Config in the service worker? Is it possible to move the service worker to the root directory instead which is in the project scope so I can use environment variables instead?
firebase-message-sw.js (Service Worker)
// Scripts for firebase and firebase messaging
importScripts('https://www.gstatic.com/firebasejs/9.0.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/9.0.0/firebase-messaging-compat.js');
// Initialize the Firebase app in the service worker by passing the generated config
firebase.initializeApp({
apiKey: "",
authDomain: "",
databaseURL: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: ""
})
// Retrieve firebase messaging
const messaging = firebase.messaging();
Registration of Service worker
getFCMToken = async () => {
try {
const registration = await navigator.serviceWorker.register('./firebase-message-sw.js')
const token = await messaging.getToken({
vapidKey: process.env.REACT_APP_FIREBASE_VAPID_KEY,
serviceWorkerRegistration: registration
})
console.log(token)
} catch (e) {
console.log('err', e)
}
}
Note: If I move the service worker into the root folder, I get this error:
DOMException: Failed to register a ServiceWorker for scope (‘http://localhost:3000/’) with script (‘http://localhost:3000/firebase-message-sw.js’): The script has an unsupported MIME type (‘text/html’).
Basically, it still tries to look for service worker inside the public folder instead of the new location.
2
Answers
I found the answer on this link: How to use process.env in a React service worker
So you have to install NPM Package
cra-append-sw
in your project.Place the service worker in the root directory or any other location that you can access
process.env
from. Use these environment variables in your service worker to initialize firebase config.Then, add these two scripts in your
package.json
file:Run the project and it should create a service worker in your public folder.
Since the service worker is loaded and initialised in the browser, the browser has to have access to your firebase config, therefore you can’t "hide" it from the user.
It is safe to publish the firebase config to your public folder, but make sure you secure your firebase backend with according rules. See https://firebase.google.com/docs/database/security/get-started and https://firebase.google.com/docs/auth/where-to-start
Maybe you should not add the config to your source repo (if public) to prevent sniffing.
The local config should be switch to the prod config during build or deploy process. Or, another option is to load a different config depending on the url: