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

Firebase Cloud Messaging报错:navigator未定义及浏览器不兼容

实现Firebase Cloud Messaging时遇到的两个问题

错误日志汇总

error - node_modules\@firebase\messaging\dist\esm\index.esm2017.js (1019:0) @ Component.WindowMessagingFactory [as instanceFactory]
error - ReferenceError: navigator is not defined
    at FirebaseProvider (./hooks/useFirebase.tsx:36:87)
null
error - node_modules\@firebase\messaging\dist\esm\index.esm2017.js (1167:0) @ eval
error - unhandledRejection: FirebaseError: Messaging: This browser doesn't support the API's required to use the Firebase SDK. (messaging/unsupported-browser).
    at eval (webpack-internal:///(sc_client)/./node_modules/@firebase/messaging/dist/esm/index.esm2017.js:1180:33) {
  code: 'messaging/unsupported-browser',
  customData: {}
}
null

问题1:navigator未定义

原因分析

navigator是浏览器环境专属的全局对象,若项目使用服务端渲染框架(如Next.js),FirebaseProvider会在服务端执行初始化逻辑,此时调用getMessaging(firebase_app)会触发Firebase SDK内部对navigator的访问,导致服务端环境下找不到该对象报错。

解决方案

将Messaging相关的初始化逻辑移到客户端专属的生命周期中(如React的useEffect),同时增加浏览器环境判断:

修改useFirebase.tsx中的FirebaseProvider:

import { useState, useEffect } from 'react';
import { Messaging, getMessaging, getToken, onMessage } from 'firebase/messaging';
// 其他必要导入保持不变

export const FirebaseProvider = ({ children }: { children: JSX.Element }) => {
  const db = getFirestore(firebase_app);
  const storage = getStorage(firebase_app);
  const functions = getFunctions(firebase_app);
  const auth = getAuth(firebase_app);
  const [messaging, setMessaging] = useState<Messaging | undefined>(undefined);
  const [saveMessagingDeviceToken, setSaveMessagingDeviceToken] = useState<(() => void) | undefined>(undefined);

  useEffect(() => {
    // 仅在浏览器环境执行Messaging相关逻辑
    if (typeof window !== 'undefined' && typeof navigator !== 'undefined') {
      const msgInstance = getMessaging(firebase_app);
      setMessaging(msgInstance);

      // 定义保存设备Token的函数
      async function saveToken() {
        if (!auth.currentUser) return;
        try {
          const currentToken = await getToken(msgInstance);
          if (currentToken) {
            console.log("Got FCM device token:", currentToken);
            const tokenRef = doc(db, "fcm_tokens", currentToken);
            await setDoc(tokenRef, { uid: auth.currentUser.uid });

            onMessage(msgInstance, (message) => {
              console.log(
                "New foreground notification from Firebase Messaging!",
                message.notification
              );
            });
          } else {
            requestNotificationsPermissions();
          }
        } catch (error) {
          console.error("Unable to get messaging token.", error);
        }
      }

      // 请求通知权限函数
      async function requestNotificationsPermissions() {
        console.log("Requesting notifications permission...");
        const permission = await Notification.requestPermission();

        if (permission === "granted") {
          console.log("Notification permission granted.");
          await saveToken();
        } else {
          console.log("Unable to get permission to notify.");
        }
      }

      setSaveMessagingDeviceToken(saveToken);
    }
  }, [auth, db]);

  return (
    <FirebaseContext.Provider
      value={{ auth, db, storage, functions, saveMessagingDeviceToken }}
    >
      {children}
    </FirebaseContext.Provider>
  );
};

问题2:浏览器不支持FCM API

原因分析

即便在Chrome和开启推送服务的Brave中出现该错误,可能的触发原因包括:

  • 项目运行在HTTP协议环境下(FCM要求HTTPS,仅localhost例外)
  • 浏览器推送权限未正确授予或被系统限制
  • Firebase Messaging的Service Worker未正确配置或注册
  • 初始化Messaging前未做浏览器兼容性校验

解决方案

  1. 确认运行环境协议:确保项目在HTTPS环境下运行(本地开发用localhost不受限制)
  2. 前置兼容性校验:在初始化Messaging前先验证浏览器支持性,修改useEffect中的逻辑:
    useEffect(() => {
      if (typeof window !== 'undefined' && typeof navigator !== 'undefined') {
        // 检查浏览器是否支持FCM所需核心API
        if (!('Notification' in window) || !('serviceWorker' in navigator)) {
          console.log("当前浏览器不支持FCM推送功能");
          return;
        }
        // 后续Messaging初始化逻辑...
      }
    }, [auth, db]);
    
  3. 配置Service Worker:确保项目根目录存在firebase-messaging-sw.js,示例内容如下:
    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: "YOUR_API_KEY",
      authDomain: "YOUR_AUTH_DOMAIN",
      projectId: "YOUR_PROJECT_ID",
      storageBucket: "YOUR_STORAGE_BUCKET",
      messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
      appId: "YOUR_APP_ID"
    });
    
    const messaging = firebase.messaging();
    
  4. 清理旧缓存:若存在旧的Service Worker缓存,可在Chrome开发者工具的Application > Service Workers面板中强制更新或注销旧缓存

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 13:25:18