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

Next JS初始化Firebase Cloud Messaging遇Navigator未定义错误求助

解决方案

方法一:条件初始化Messaging(基础版)

直接在Firebase配置文件中,仅在客户端环境初始化Messaging对象,避免服务端执行依赖浏览器的代码:

import { initializeApp } from "firebase/app";
import { getAuth } from 'firebase/auth';
import { getFirestore } from "firebase/firestore";
import { getStorage } from 'firebase/storage';
import { getMessaging } from "firebase/messaging";

const firebaseConfig = {
    apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
    authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
    projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
    storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
    messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
    appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
};

const app = initializeApp(firebaseConfig);

export const db = getFirestore(app);
export const auth = getAuth(app);
export const storage = getStorage(app);

// 仅在浏览器环境(window存在)时初始化Messaging
export const messaging = typeof window !== 'undefined' ? getMessaging(app) : null;

使用时,在客户端组件(需添加'use client'指令)中先判断messaging是否存在,再执行FCM相关逻辑:

'use client';

import { messaging } from '@/lib/firebase';
import { getToken } from "firebase/messaging";
import { useEffect } from 'react';

useEffect(() => {
  if (!messaging) return;

  // 请求通知权限并获取token
  async function getFCMToken() {
    const permission = await Notification.requestPermission();
    if (permission === 'granted') {
      const token = await getToken(messaging, { vapidKey: '你的VAPID密钥' });
      console.log('FCM Token:', token);
      // 后续可将token发送到后端存储
    }
  }

  getFCMToken();
}, []);

方法二:动态导入Messaging(更安全)

如果直接导入getMessaging在服务端就会报错(部分Firebase版本存在这种情况),可以改用动态导入,仅在客户端加载Messaging模块:

修改Firebase配置文件

import { initializeApp } from "firebase/app";
import { getAuth } from 'firebase/auth';
import { getFirestore } from "firebase/firestore";
import { getStorage } from 'firebase/storage';

const firebaseConfig = {
    apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
    authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
    projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
    storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
    messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
    appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
};

const app = initializeApp(firebaseConfig);

export const db = getFirestore(app);
export const auth = getAuth(app);
export const storage = getStorage(app);

// 导出初始化Messaging的异步函数
export const getMessagingInstance = async () => {
  if (typeof window === 'undefined') return null;
  // 动态导入Messaging模块
  const { getMessaging } = await import("firebase/messaging");
  return getMessaging(app);
};

在客户端组件中使用

'use client';

import { getMessagingInstance } from '@/lib/firebase';
import { getToken } from "firebase/messaging";
import { useEffect } from 'react';

useEffect(() => {
  async function setupFCM() {
    const messaging = await getMessagingInstance();
    if (!messaging) return;

    const permission = await Notification.requestPermission();
    if (permission === 'granted') {
      const token = await getToken(messaging, { vapidKey: '你的VAPID密钥' });
      console.log('FCM Token:', token);
    }
  }

  setupFCM();
}, []);

注意事项

  • 确保你的Next.js组件使用'use client'指令,因为FCM相关逻辑只能在客户端执行。
  • 需要在项目的public目录下添加firebase-messaging-sw.js服务工作者文件,否则FCM无法正常接收后台消息。文件内容示例:
importScripts('https://www.gstatic.com/firebasejs/9.23.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/9.23.0/firebase-messaging-compat.js');

firebase.initializeApp({
  apiKey: "你的API_KEY",
  authDomain: "你的AUTH_DOMAIN",
  projectId: "你的PROJECT_ID",
  storageBucket: "你的STORAGE_BUCKET",
  messagingSenderId: "你的MESSAGING_SENDER_ID",
  appId: "你的APP_ID"
});

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: '/firebase-logo.png'
  };

  self.registration.showNotification(notificationTitle, notificationOptions);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:33:16