You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js公共目录的Firebase Cloud Messaging Service Worker中使用环境变量

在Next.js中为公共目录的Service Worker注入环境变量

我完全懂你的困扰——公共目录下的静态文件会被Next.js原样复制到输出目录,根本不会经过Webpack的编译流程,所以process.env变量自然没法被替换成实际的环境值。下面给你两种我在项目里实际用过的可行方案:

方案一:构建时动态生成Service Worker文件

这是最直接稳定的方法,通过Node脚本在开发或构建前自动生成带有环境变量的firebase-messaging-sw.js,而且生成的文件可以加入.gitignore,完全不用在Git里管理敏感配置。

具体步骤:

  1. 在项目根目录创建scripts文件夹,新建generate-sw.js脚本:
const fs = require('fs');
const path = require('path');

// 用环境变量拼接Service Worker的完整内容
const swContent = `
importScripts('https://www.gstatic.com/firebasejs/8.8.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.8.1/firebase-messaging.js');
firebase.initializeApp({
  apiKey: "${process.env.NEXT_PUBLIC_API_KEY}",
  authDomain: "${process.env.NEXT_PUBLIC_AUTH_DOMAIN}",
  projectId: "${process.env.NEXT_PUBLIC_PROJECT_ID}",
  storageBucket: "${process.env.NEXT_PUBLIC_STORAGE_BUCKET}",
  messagingSenderId: "${process.env.NEXT_PUBLIC_MESSAGING_SENDER_ID}",
  appId: "${process.env.NEXT_PUBLIC_APP_ID}",
  measurementId: "${process.env.NEXT_PUBLIC_MEASUREMENT_ID}",
});
firebase.messaging();
firebase.messaging().setBackgroundMessageHandler((payload) => console.log('payload', payload));
`.trim();

// 将内容写入public目录的目标文件
const targetPath = path.join(__dirname, '../public/firebase-messaging-sw.js');
fs.writeFileSync(targetPath, swContent);
  1. 修改package.json的脚本,让开发和构建前自动执行这个生成脚本:
"scripts": {
  "predev": "node scripts/generate-sw.js",
  "dev": "next dev",
  "prebuild": "node scripts/generate-sw.js",
  "build": "next build",
  "start": "next start"
}

这里用predev和prebuild前缀是Next.js的特性——它会在执行dev或build命令前自动运行带对应前缀的脚本。

  1. 把生成的public/firebase-messaging-sw.js加入.gitignore,避免提交到Git:
# .gitignore
public/firebase-messaging-sw.js

这样每次启动开发服务或构建项目时,脚本都会读取当前环境变量,生成最新的Service Worker文件,完美解决公共目录无法使用环境变量的问题。

方案二:客户端传递配置给Service Worker

如果不想用构建脚本,也可以通过客户端传递配置的方式实现,但步骤稍复杂,且需要处理好时机问题:

  1. 在客户端(比如pages/_app.js)初始化Firebase时,准备好配置并注册Service Worker,之后发送配置消息:
import { initializeApp } from "firebase/app";
import { getMessaging } from "firebase/messaging";

const firebaseConfig = {
  apiKey: process.env.NEXT_PUBLIC_API_KEY,
  authDomain: process.env.NEXT_PUBLIC_AUTH_DOMAIN,
  projectId: process.env.NEXT_PUBLIC_PROJECT_ID,
  storageBucket: process.env.NEXT_PUBLIC_STORAGE_BUCKET,
  messagingSenderId: process.env.NEXT_PUBLIC_MESSAGING_SENDER_ID,
  appId: process.env.NEXT_PUBLIC_APP_ID,
  measurementId: process.env.NEXT_PUBLIC_MEASUREMENT_ID,
};

// 初始化客户端Firebase
const app = initializeApp(firebaseConfig);

// 注册Service Worker并发送配置
navigator.serviceWorker.register('/firebase-messaging-sw.js')
  .then(registration => {
    // 确保Service Worker激活后再发消息
    if (registration.active) {
      registration.active.postMessage({
        type: 'SET_FIREBASE_CONFIG',
        config: firebaseConfig
      });
    } else {
      // 监听Service Worker激活事件
      registration.addEventListener('updatefound', () => {
        const newWorker = registration.installing;
        newWorker.addEventListener('statechange', () => {
          if (newWorker.state === 'activated') {
            newWorker.postMessage({
              type: 'SET_FIREBASE_CONFIG',
              config: firebaseConfig
            });
          }
        });
      });
    }
  });
  1. 修改Service Worker,监听消息并初始化Firebase:
importScripts('https://www.gstatic.com/firebasejs/8.8.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.8.1/firebase-messaging.js');

// 监听来自客户端的配置消息
self.addEventListener('message', (event) => {
  if (event.data.type === 'SET_FIREBASE_CONFIG') {
    const firebaseConfig = event.data.config;
    firebase.initializeApp(firebaseConfig);
    firebase.messaging();
    firebase.messaging().setBackgroundMessageHandler((payload) => console.log('payload', payload));
  }
});

这种方法的缺点是:如果Service Worker在客户端发送消息前就完成了初始化,会导致配置加载失败,需要额外处理激活时机问题。所以相比之下,方案一更省心可靠。

内容的提问来源于stack exchange,提问作者Wataru Ono

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 11:32:29