Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use process.env in a React service worker

I am trying to set-up a Firebase-messaging-sw.js file (for web push notifications). I am wondering if there is a way to avoid exposing my Firebase config data to the public as much as possible - though it might be revealed anyways? (I'm not too sure about the nuances)

I've tried following: How can I customize my Service Worker based on environment variables? But the answer's swEnvbuild doesn't seem to be running, as the swenv.js file is not found. I suspect it might need to be set-up differently in React?

(first question, please feel free to provide constructive criticisms of my question)

like image 966
Alexander Kim Avatar asked Jun 05 '20 23:06

Alexander Kim


People also ask

How do you write process env in react?

Using a .env fileconst { REACT_APP_MY_ENV } = process. env; Assuming the application was created with create-react-app, this will work out of the box, with no additional work. If the application was not created with create-react-app, add the dotenv package to the project.

How do I see process env in react?

There's only one gotcha, to access environment variables from the client app they must be prefixed with REACT_APP_ . Otherwise they will only be accessible on the server side. You can access environment variables (with the REACT_APP_ prefix) from your React app via the Node. js process.

How .env file works in react?

env file in our react js project. If you are using some external APIs for data you must use the . env file to store your sensitive credentials like API keys. Environment variables can also help us to store our API link in one location so that we don't have to change the link in each file manually.


1 Answers

I recently had to do this with a CRA app, it's not easy to find information on it so I figured I should share my solution. Assuming you've already changed serviceWorker.unregister() to serviceWorker.register() in ./src/index.js, and have a .env file with your variables set in the root of your project, then you can update ./src/serviceWorker.js to include your process.env variables as a query string.

In the register function in serviceWorker.js, update const swUrl as shown below, notice the const firebaseConfig w/process.env, declared before swUrl..
./src/serviceWorker.js:

// Convert environment variables to URL `search` parameters
const firebaseConfig = new URLSearchParams({
  apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
  authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
  databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL,
  projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
  storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.REACT_APP_FIREBASE_APP_ID,
  measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID
}).toString();

// Service worker URL w/config variables
const swUrl = `${process.env.PUBLIC_URL}/firebase-messaging-sw.js?${firebaseConfig}`;

then in ./public/firebase-messaging-sw.js (create it if it doesn't exist), you can do something like the following..
./public/firebase-messaging-sw.js

importScripts('https://www.gstatic.com/firebasejs/8.0.2/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.0.2/firebase-messaging.js');

// Set Firebase configuration, once available
self.addEventListener('fetch', () => {
  const urlParams = new URLSearchParams(location.search);
  self.firebaseConfig = Object.fromEntries(urlParams);
});

// "Default" Firebase configuration (prevents errors)
const defaultConfig = {
  apiKey: true,
  projectId: true,
  messagingSenderId: true,
  appId: true,
};

// Initialize Firebase app
firebase.initializeApp(self.firebaseConfig || defaultConfig);
const messaging = firebase.messaging();

// Configure message handler (assumes backend is set up)
messaging.onBackgroundMessage((payload) => {
  const { icon, body, title } = payload.data;
  self.registration.showNotification(title, { body, icon });
});    

If there's a more ideal solution, would love to hear about it, but this configuration worked for me.

like image 79
iPzard Avatar answered Oct 10 '22 17:10

iPzard