基于Vite的React应用中FCM Token失效问题求助
问题分析与解决方案
核心问题
你的代码仅在组件初始化时获取一次FCM Token,但FCM Token会在多种场景下自动刷新(如服务 worker 更新、浏览器存储变更、设备信息改动),而你未监听Token刷新事件,导致后端保存的旧Token失效后无法自动更新,最终出现「设备不存在」的错误。同时主应用用Firebase SDK v9、服务工作线程用v8的版本差异,可能引发隐性兼容性问题,加剧Token刷新异常。
具体解决方案
1. 监听Token刷新事件,自动同步后端存储
在Notification.jsx中添加Token刷新监听逻辑,当Token更新时自动同步到本地存储和后端:
修改后的Notification.jsx关键代码:
import { useEffect } from "react"; import { messaging } from "../firebase"; import { getToken, onMessage, onTokenRefresh } from "firebase/messaging"; // 引入刷新监听方法 import api from "../axiosInstance"; import { saveFcmToken, getFcmToken } from "../utils/storage"; // 新增读取本地Token方法 function Notification() { useEffect(() => { // 封装Token同步逻辑,避免重复请求 const syncToken = async (newToken) => { const existingToken = await getFcmToken(); if (newToken !== existingToken) { await saveFcmToken(newToken); await api.post("/save-token", { fcmToken: newToken }); console.log("Token updated successfully:", newToken); } }; const requestPermission = async () => { try { const registration = await navigator.serviceWorker.ready; const token = await getToken(messaging, { vapidKey: 'YOUR_VAPID_KEY', serviceWorkerRegistration: registration, }); if (token) { await syncToken(token); } } catch (err) { console.error("Error getting token: ", err); } }; // 监听Token自动刷新 const unsubscribeRefresh = onTokenRefresh(async () => { try { const registration = await navigator.serviceWorker.ready; const newToken = await getToken(messaging, { vapidKey: 'YOUR_VAPID_KEY', serviceWorkerRegistration: registration, }); if (newToken) { await syncToken(newToken); } } catch (err) { console.error("Error refreshing token: ", err); } }); // 监听前台消息 const unsubscribeMessage = onMessage(messaging, (payload) => { console.log("Message received.", payload); }); // 监听通知权限变化,重新授权后自动获取Token const handlePermissionChange = () => { if (Notification.permission === "granted") { requestPermission(); } }; Notification.requestPermission().then(handlePermissionChange); navigator.permissions.query({ name: "notifications" }).then(permissionStatus => { permissionStatus.onchange = handlePermissionChange; }); requestPermission(); // 清理所有订阅 return () => { unsubscribeRefresh(); unsubscribeMessage(); }; }, []); return null; } export default Notification;
2. 统一Firebase SDK版本
将服务工作线程的SDK升级到v9,消除版本差异导致的兼容性问题:
修改后的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-app.firebaseapp.com", projectId: "your-app", storageBucket: "your-app.appspot.com", messagingSenderId: "YOUR_SENDER_ID", appId: "YOUR_APP_ID", measurementId: "YOUR_MEASUREMENT_ID" }); const messaging = firebase.messaging(); messaging.onBackgroundMessage((payload) => { console.log("Received background message", payload); const notificationTitle = payload.notification.title; const notificationOptions = { body: payload.notification.body, icon: 'your-icon.png', }; self.registration.showNotification(notificationTitle, notificationOptions); });
3. 后端补充Token失效处理
在后端发送推送时,捕获「设备不存在」的错误,自动从数据库中删除失效Token,避免后续重复无效请求。
关键说明
- FCM Token刷新由系统自动触发,必须通过
onTokenRefresh监听并同步到后端; - SDK版本不一致会导致服务 worker 无法正确接收刷新事件,统一版本是必要操作;
- 监听通知权限变化,确保用户重新授权后能自动获取新Token。
内容的提问来源于stack exchange,提问作者rave
相关产品推荐
相关产品推荐

