[英]How to use process.env in a React service worker
我正在嘗試設置 Firebase-messaging-sw.js 文件(用於 web 推送通知)。 我想知道是否有辦法避免將我的 Firebase 配置數據盡可能地暴露給公眾——盡管它可能會被泄露? (我不太確定細微差別)
我嘗試了以下方法: 如何根據環境變量自定義我的 Service Worker? 但是答案的 swEnvbuild 似乎沒有運行,因為沒有找到 swenv.js 文件。 我懷疑它可能需要在 React 中進行不同的設置?
(第一個問題,請隨時對我的問題提出建設性的批評)
我最近不得不用一個 CRA 應用程序來做這件事,要找到它的信息並不容易,所以我想我應該分享我的解決方案。 假設您已經在 ./src/index.js 中將 serviceWorker.unregister( serviceWorker.unregister()
更改為./src/index.js
serviceWorker.register()
,並且在項目的根目錄中設置了一個帶有變量的.env
文件,那么您可以更新./src/serviceWorker.js
將您的process.env
變量包含為查詢字符串。
在 serviceWorker.js 中的register
serviceWorker.js
中,更新const swUrl
如下所示,注意const firebaseConfig
firebaseConfig w/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}`;
然后在./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 });
});
如果有更理想的解決方案,很想聽聽,但這種配置對我有用。
我發現這篇文章使用cra-append-sw到 append 環境變量。 然后我在package.json
中創建了兩個pre
腳本。 當我運行npm start
腳本運行創建一個[root folder]/public/firebase-messaging-sw.js
prestart
環境變量的文件(在被 webpack 處理之后)。
我創建了一個[root folder]/firebase-messaging-sw.js
。 此文件將由 webpack 處理,替換環境變量的值。
// 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);
});
然后我有[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...
最后,我在package.json
中添加了 2 個pre
腳本
...
"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",
...
我自己在這個問題上遇到了真正的麻煩。 服務工作者在您的環境啟動之前就參與了堆棧方式,因此它無權訪問您的.Env
變量是有道理的。
我的解決方案
我構建了一個 npm 模塊,該模塊在構建時使用 webpack 從 your.env 文件中提取“安全”版本控制變量並將它們放入獨立的 JS 文件中。 然后,您可以提前 go 並導入此文件並在您的服務人員中使用它。
https://www.npmjs.com/package/vue-enverywhere
免責聲明:
我知道這是針對 vue 的,但它的 webpack,它不是 vue 特定的。 此外,您最好只復制代碼而不使用模塊。 這對我自己來說更像是一個有趣的練習:)
在 index.js 文件中(或任何你想注冊 service worker 的地方):
if ("serviceWorker" in navigator) {
console.log("Registration started");
const firebaseConfig = encodeURIComponent(
JSON.stringify({
apiKey: process.env.FCM_API_KEY,
projectId: process.env.FCM_PROJECT_ID,
messagingSenderId: process.env.FCM_SENDER_ID,
appId: process.env.FCM_APP_ID,
})
);
navigator.serviceWorker
.register(
`../../../firebase-messaging-sw.js?firebaseConfig=${firebaseConfig}`
)
.then(function (registration) {
console.log("Registration successful, scope is:", registration.scope);
})
.catch(function (err) {
console.log("Service worker registration failed, error:", err);
});
在 Service Worker 中,firebase-messaging-sw.js:
importScripts("https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js");
importScripts(
"https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js"
);
firebase.initializeApp(
JSON.parse(new URL(location).searchParams.get("firebaseConfig"))
);
firebase.messaging();
這足以在發送通知類型消息時接收后台推送通知。
此解決方案將起作用,只需記住根據您的項目編輯 Service-worer 文件的路徑(在 index.js 左右注冊時),否則它會給出“Mime 錯誤”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.