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

Nextjs集成Firebase Messaging时出现Reference error: self is not defined

解决Next.js + Firebase Messaging 8.10.0 出现「Reference error: self is not defined」的问题

错误原因

Next.js 是服务端渲染(SSR)框架,你的Notification组件被导入到_app.js后,会在服务端和客户端都执行。而 Firebase Messaging 的初始化代码依赖浏览器环境的全局对象self,服务端没有这个对象,因此触发报错。

修复方案

1. 动态导入 Notification 组件,禁用 SSR

在_app.js中不要直接导入组件,改用 Next.js 的dynamic函数导入,指定仅在客户端渲染:

import dynamic from 'next/dynamic'

const Notification = dynamic(() => import('../components/Notification'), {
  ssr: false
})

function MyApp({ Component, pageProps }) {
  return (
    <>
      <Notification />
      <Component {...pageProps} />
    </>
  )
}

export default MyApp

2. 在 Firebase 工具文件中做环境判断

修改Firebase.js,确保仅在浏览器环境下初始化 Messaging:

import firebase from 'firebase/app'
import 'firebase/messaging'

let messaging = null

// 仅在浏览器环境初始化
if (typeof self !== 'undefined') {
  const firebaseConfig = {
    // 你的 Firebase 配置信息
  }

  if (!firebase.apps.length) {
    firebase.initializeApp(firebaseConfig)
    messaging = firebase.messaging()
  }
}

export const requestToken = async () => {
  if (!messaging) return null
  
  try {
    const token = await messaging.getToken({
      vapidKey: '你的 VAPID 公钥'
    })
    return token
  } catch (error) {
    console.error('获取推送令牌失败:', error)
    return null
  }
}

3. 在组件中仅在客户端注册 Service Worker

在Notification.js中,使用useEffect钩子确保 Service Worker 注册逻辑仅在浏览器执行:

import { useEffect } from 'react'
import { requestToken } from '../utils/Firebase'

export default function Notification() {
  useEffect(() => {
    // 检查浏览器是否支持 Service Worker
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('/firebase-messaging-sw.js')
        .then(async (registration) => {
          // 关联 Service Worker 和 Messaging
          const messaging = await import('firebase/messaging').then(m => m.default.messaging())
          messaging.useServiceWorker(registration)
          // 请求推送令牌
          const token = await requestToken()
          console.log('推送令牌:', token)
        })
        .catch(error => {
          console.error('Service Worker 注册失败:', error)
        })
    }
  }, [])

  return null // 该组件无需渲染 UI
}

额外注意事项

  • 确保firebase-messaging-sw.js放在public文件夹根目录,Next.js 会将其作为静态资源对外暴露,Service Worker 才能正确被加载。
  • 验证你的 Firebase 配置和 VAPID 密钥是否正确,VAPID 密钥需要在 Firebase 控制台的「云消息传递」中生成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 06:30:47