skip to Main Content

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


  1. Chosen as BEST ANSWER

    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:

    "scripts": {
      "prestart": "cra-append-sw --mode dev --env ./.env.dev ./firebase-message-sw.js",
      "prebuild": "cra-append-sw --mode build --env ./.env.prod ./firebase-message-sw.js"
    }
    

    Run the project and it should create a service worker in your public folder.


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

    if(isLocalhost()) ? LoadLocalConfig() : LoadProdConfig();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search