在极简React应用中无法获取FCM token的问题求助
解决CRA PWA TypeScript项目中FCM Service Worker MIME类型错误问题
问题根源
你将firebase-messaging-sw.js放在了项目根目录,但CRA仅会把public目录下的文件识别为静态资源。访问根目录文件时,会被React路由 fallback 到index.html,返回text/html类型,导致Service Worker注册失败。
修复步骤
- 移动Service Worker文件:把
firebase-messaging-sw.js移到项目的public目录下,此时访问路径http://localhost:3000/firebase-messaging-sw.js会返回正确的application/javascript类型。 - 明确指定FCM的Service Worker:在Firebase初始化代码中,手动注册并指定该Service Worker,避免和CRA默认的PWA Service Worker冲突。
修改后的App.tsx示例
import React, { useEffect } from 'react'; import './App.css'; import { initializeApp } from 'firebase/app'; import { getMessaging, getToken, onMessage } from 'firebase/messaging'; // 替换为你的Firebase配置 const firebaseConfig = { 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 app = initializeApp(firebaseConfig); const messaging = getMessaging(app); function App() { useEffect(() => { const requestPermissionAndGetToken = async () => { const permission = await Notification.requestPermission(); if (permission === 'granted') { try { // 手动注册FCM的Service Worker并获取Token const token = await getToken(messaging, { vapidKey: "YOUR_VAPID_KEY", // 从Firebase控制台获取 serviceWorkerRegistration: await navigator.serviceWorker.register('/firebase-messaging-sw.js') }); console.log('FCM Token:', token); } catch (error) { console.error('获取Token失败:', error); } } }; requestPermissionAndGetToken(); // 监听前台消息 onMessage(messaging, (payload) => { console.log('收到前台消息:', payload); }); }, []); return ( <div className="App"> <h1>FCM测试页面</h1> </div> ); } export default App;
public目录下的firebase-messaging-sw.js示例
// 引入对应版本的Firebase兼容库(需和项目中安装的Firebase版本匹配) 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'); const firebaseConfig = { // 和App.tsx中一致的配置 }; firebase.initializeApp(firebaseConfig); const messaging = firebase.messaging(); // 可选:处理后台消息推送 messaging.onBackgroundMessage((payload) => { const notificationTitle = payload.notification?.title || '新消息'; const notificationOptions = { body: payload.notification?.body || '收到一条后台消息', icon: '/logo192.png' // 使用项目public目录下的图标 }; self.registration.showNotification(notificationTitle, notificationOptions); });
额外注意事项
- 确保
firebase-messaging-sw.js中引入的Firebase版本和项目依赖的版本一致,避免兼容性问题。 - 若不需要CRA默认的PWA Service Worker,可在
src/index.tsx中注释掉serviceWorkerRegistration.register()相关代码,减少冲突。 - 测试时,
localhost环境无需HTTPS(Chrome例外允许),正式环境必须使用HTTPS才能正常注册Service Worker。
内容的提问来源于stack exchange,提问作者nPn
相关产品推荐
相关产品推荐

