如何在 React Service Worker 中使用 process.env

Ale*_*Kim 12 reactjs service-worker web-push firebase-cloud-messaging

我正在尝试设置 Firebase-messaging-sw.js 文件(用于网络推送通知)。我想知道是否有办法尽可能避免将我的 Firebase 配置数据暴露给公众——尽管它可能会被泄露?(我不太确定细微差别)

我尝试了以下方法:如何根据环境变量自定义 Service Worker?但是答案的 swEnvbuild 似乎没有运行,因为找不到 swenv.js 文件。我怀疑它可能需要在 React 中进行不同的设置?

(第一个问题,请随时对我的问题提出建设性的批评意见)

iPz*_*ard 8

我最近不得不用一个 CRA 应用程序来做这个,找到它的信息并不容易,所以我想我应该分享我的解决方案。假设您已经更改serviceWorker.unregister()serviceWorker.register()in ./src/index.js,并且.env在项目的根目录中有一个包含变量设置的文件,那么您可以更新./src/serviceWorker.js以将您的process.env变量包含为查询字符串。

在 中的register函数中serviceWorker.js,更新const swUrl如下所示,注意const firebaseConfigw/process.env,在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}`;
Run Code Online (Sandbox Code Playgroud)

然后在./public/firebase-messaging-sw.js(如果它不存在则创建它),您可以执行以下操作
../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 });
});    
Run Code Online (Sandbox Code Playgroud)

如果有更理想的解决方案,很想听听,但这种配置对我有用。


Jon*_*lez 5

我发现这篇文章使用cra-append-sw来附加环境变量。然后我pre在我的package.json. 当我运行npm startprestart脚本运行创造一个[root folder]/public/firebase-messaging-sw.js包含ENV瓦尔(通过的WebPack处理后)文件。

执行

我创建了一个[root folder]/firebase-messaging-sw.js. 这个文件将由 webpack 处理,替换 env vars 的值。

// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here. Other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/8.1.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.1.1/firebase-messaging.js');

// Initialize the Firebase app in the service worker by passing in
// your app's Firebase config object.
// https://firebase.google.com/docs/web/setup#config-object
firebase.initializeApp({
    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,
});

// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();
messaging.onBackgroundMessage(function (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: '/logo.png'
    };

    self.registration.showNotification(notificationTitle, notificationOptions);
});
Run Code Online (Sandbox Code Playgroud)

然后我有[root folder]/.env.dev[root folder]/.env.prod

REACT_APP_FIREBASE_API_KEY=A...
REACT_APP_FIREBASE_AUTH_DOMAIN=d...
REACT_APP_FIREBASE_DATABASE_URL=h...
REACT_APP_FIREBASE_PROJECT_ID=d...
REACT_APP_FIREBASE_STORAGE_BUCKET=d...
REACT_APP_FIREBASE_MESSAGING_SENDER_ID=7...
REACT_APP_FIREBASE_APP_ID=1...
REACT_APP_FIREBASE_MEASUREMENT_ID=G...
Run Code Online (Sandbox Code Playgroud)

最后,我pre在我的package.json

...
"scripts": {
    "prestart": "cra-append-sw --mode dev --env ./.env.dev ./firebase-messaging-sw.js",
    "prebuild": "cra-append-sw --mode build --env ./.env.prod ./firebase-messaging-sw.js",
...
Run Code Online (Sandbox Code Playgroud)