skip to Main Content

I’m integrating Firebase Cloud Messaging, and it is required to have firebase-messaging-sw.js file inside the public folder as a service worker.
The file needs to have my firebase config, which I of course want to hide the details of in environment veriables. I have the object defined as such:

const firebaseConfig = {
    apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
    authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
    projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
    storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
    messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
    appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
    measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};

But now when I give permissions for notifications and it tries to register the service worker, I got the error: caught ReferenceError: process is not defined.
I have the variables defined in a .env.local file, and I’ve been using these same variables in my app in other places successfully.

How can I access them from a file in the public folder?

2

Answers


  1. You need to prefix your environment variable with NEXT_PUBLIC_ in order for them to work in a file in the public directory.

    As quoted from documentation,

    In order to expose a variable to the browser you have to prefix the
    variable with NEXT_PUBLIC_

    You don’t access the process.env in your public file, rather you pass its value to the public file at build time as per the documentation example.

    The value will be inlined into JavaScript sent to the browser because
    of the NEXT_PUBLIC_ prefix. This inlining occurs at build time, so
    your various NEXT_PUBLIC_ envs need to be set when the project is
    built.

    So, you import a setup function from your public folder file that sets the environment variables values at built time, on your public file code I assume you can name them whatever you like, you don’t use process.env as the environment variables are of course not available for the browser.

    So, then the significance of the prefix NEXT_PUBLIC_ is just to be able to access the process env variables values in the Next react/typescript client side code, not in the public folder JavaScript files themselves, (the stress on the values of environment variables because you can’t access actual web server process, that’s why dynamic lookups don’t work as stated in the docs)

    // This will NOT be inlined, because it uses a variable
    const varName = 'NEXT_PUBLIC_ANALYTICS_ID'
    setupAnalyticsService(process.env[varName])
    
    // This will NOT be inlined, because it uses a variable
    const env = process.env
    setupAnalyticsService(env.NEXT_PUBLIC_ANALYTICS_ID)
    
    Login or Signup to reply.
  2. Files in the public folder in nextjs don’t go through the webpack build process hence why process is undefined.

    To use environment variables in your firebase-messaging-sw.js file, check the steps below.

    First, create a .env.local file, skip this step if you already have it.

    Install the dotenv package with npm i dotenv, will we use it to load the environment variables.

    Create a file called swEnvBuild.js in the root directory.
    In swEnvBuild.js file you just created, we will create a function that loads the .env.local file and then writes the contents of the file into a new file in the public folder called swenv.js

    //swEnvBuild.js        
    require('dotenv').config({ path: '.env.local' }); // make sure you have '.env.local' file.    
    const fs = require('fs');
    
    fs.writeFileSync(
      './public/swenv.js',
      `
     const process = {
              env: {
                NEXT_PUBLIC_FIREBASE_API_KEY: '${process.env.NEXT_PUBLIC_FIREBASE_API_KEY}',
                NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: '${process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN}',
                NEXT_PUBLIC_FIREBASE_PROJECT_ID: '${process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID}',
                NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET: '${process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET}',
                NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: '${process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID}',
                NEXT_PUBLIC_FIREBASE_APP_ID: '${process.env.NEXT_PUBLIC_FIREBASE_APP_ID}',
                NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID: '${process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID}'
      }
     }`
    );
    

    Then we import the file that will be generated from swEnvBuild.js called swenv.js in the firebase-messaging-sw.js file.

    //firebase-messaging-sw.js    
    importScripts('swenv.js'); // this file should have all the environment variables declared, allowing you to use process.env.ANY_KEY_YOU_DEFINED
    
    // Initialize the Firebase app in the service worker by passing the generated config
    const firebaseConfig = {
        apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
        authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
        projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
        storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
        messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
        appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
        measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
    };
    

    Finally, update your package.json.

    "scripts": {
            "dev": "node swEnvBuild.js && next dev ",
            "build": "next build && node swEnvBuild.js",
     },
    

    After running npm run dev, your environment variables should be accessible in firebase-messaging-sw.js using process.env

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search