React项目中如何为public目录下的firebase-messaging-sw.js提供环境变量
解决React中Firebase Messaging Service Worker访问环境变量的问题
核心原因
Create React App(CRA)的public目录下的文件属于静态资源,不会经过webpack的环境变量替换处理,因此无法直接使用process.env.REACT_APP_*这类变量。
可行解决方案
方案一:构建时自动生成包含环境变量的swenv.js文件
这是最直接的方案,通过脚本在构建前读取.env变量,生成一个可被service worker引入的环境变量文件:
- 创建生成环境变量的脚本
在项目根目录新建generate-sw-env.js文件,内容如下:
const fs = require('fs'); const path = require('path'); // 从process.env中提取需要的Firebase配置 const envVars = { apiKey: process.env.REACT_APP_APIKEY, authDomain: process.env.REACT_APP_AUTHDOMAIN, projectId: process.env.REACT_APP_PROJECTID, storageBucket: process.env.REACT_APP_STORAGEBUCKET, messagingSenderId: process.env.REACT_APP_MESSAGINGSENDERID, appId: process.env.REACT_APP_APPID, measurementId: process.env.REACT_APP_MEASUREMENTID, }; // 生成swenv.js内容,将变量挂载到self对象上 const content = `self.FIREBASE_CONFIG = ${JSON.stringify(envVars)};`; // 将文件写入public目录 fs.writeFileSync(path.join(__dirname, 'public', 'swenv.js'), content);
- 修改package.json的构建脚本
在scripts中添加预构建命令,确保每次构建前都生成最新的swenv.js:
{ "scripts": { "prebuild": "node generate-sw-env.js", "prestart": "node generate-sw-env.js", "start": "react-scripts start", "build": "react-scripts build" } }
- 修改firebase-messaging-sw.js中的变量引用
把原来的process.env替换为self.FIREBASE_CONFIG:
//firebase-messaging.sw.js // eslint-disable-next-line no-undef importScripts("https://www.gstatic.com/firebasejs/8.10.1/firebase-app.js"); // eslint-disable-next-line no-undef importScripts( "https://www.gstatic.com/firebasejs/8.10.1/firebase-messaging.js" ); importScripts("swenv.js"); firebase.initializeApp(self.FIREBASE_CONFIG); const messaging = firebase.messaging(); messaging.onBackgroundMessage((payload) => { console.log( "[firebase-messaging-sw.js] Received background message ", payload ); const notificationTitle = payload.notification.title; const notificationOptions = { body: payload.notification.body, icon: payload.notification.image, }; // eslint-disable-next-line no-restricted-globals self.registration.showNotification(notificationTitle, notificationOptions); });
方案二:将Service Worker移入src目录并通过webpack处理(需自定义CRA配置)
如果不想额外维护脚本,可以通过customize-cra修改webpack配置,让service worker文件被webpack处理,从而支持环境变量:
- 安装依赖
npm install customize-cra react-app-rewired --save-dev
- 修改package.json的scripts
{ "scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test" } }
- 在根目录创建config-overrides.js
const { override, addWebpackPlugin } = require('customize-cra'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const path = require('path'); module.exports = override( addWebpackPlugin( new CopyWebpackPlugin({ patterns: [ { from: path.resolve(__dirname, 'src/firebase-messaging-sw.js'), to: path.resolve(__dirname, 'build'), }, ], }) ) );
- 将firebase-messaging-sw.js移到src目录
此时文件会被webpack处理,直接使用process.env.REACT_APP_*即可,无需引入swenv.js。
注意事项
- Firebase的
apiKey等配置本身是公开可访问的(前端应用无法完全隐藏这些配置),Firebase的安全机制依赖于规则设置(如Firestore规则、Storage规则),而非隐藏这些凭证。 - 确保.env文件已添加到.gitignore中,避免提交敏感信息。
内容的提问来源于stack exchange,提问作者Coolkid
相关产品推荐
相关产品推荐

