Hooks
use-fcm
11/14/2025, 3:30:43 AM modified by MarvinA hook to handle Firebase Cloud Messaging, including token management, permission requests, and message handling.
Installation
Loading...
Notice
- Please move
firebase-messaging-sw.jsfromsrc/publictopublicfolder manually. - Please replace
firebaseConfiginuse-fcm/helper.tswith your own Firebase configuration.
const firebaseConfig = {
// Your own Firebase configuration
};Preview
Nothing to show.
// @ts-nocheckimport type { MessagePayload } from 'firebase/messaging';import { onMessage as onMessage_ } from 'firebase/messaging';import { useEffect } from 'react';import { getFCMToken, messaging } from './helper';const vapidKey = 'Your Vapid Key';export function useFCM({ onMessage, onToken,}: { onMessage?: (payload: MessagePayload) => void; onToken?: (token: string) => void;}) { useEffect(() => { getFCMToken({ vapidKey, }).then((token) => { if (token) { onToken?.(token); } }); }, [onToken]); useEffect(() => { if (!onMessage) { return; } const unsubscribe = onMessage_(messaging(), onMessage); return () => unsubscribe(); }, [onMessage]);}// @ts-nocheckimport { initializeApp } from 'firebase/app';import { type GetTokenOptions, getMessaging, getToken, isSupported } from 'firebase/messaging';import { requestPermission } from '@/lib';const firebaseConfig = { apiKey: 'AIzaSyCN99e2MFNFCBgZAh4YjbboM7dx4L208cc', authDomain: 'my-awesome-20250904.firebaseapp.com', projectId: 'my-awesome-20250904', storageBucket: 'my-awesome-20250904.firebasestorage.app', messagingSenderId: '447700238822', appId: '1:447700238822:web:57170ca06a374c10671627', measurementId: 'G-L0TVC48MM3',};// Initialize Firebaseconst app = initializeApp(firebaseConfig);// Initialize Firebase Cloud Messaging and get a reference to the serviceexport const messaging = () => getMessaging(app);export async function getFCMToken(params: Pick<GetTokenOptions, 'vapidKey'>) { const { vapidKey } = params; const permission = await requestPermission(); if (typeof window !== 'undefined' && 'serviceWorker' in navigator && permission === 'granted') { try { if (!(await isSupported())) { return; } return await getToken(messaging(), { vapidKey, }); } catch (error) { console.error('getFCMToken error:', error); } }}const logger = console.log;// some key maybe unnecessary, but keep it for nowconst searchKey = '__s';const searchValue = 'n';const storageKey = 'storageKey';const CHANNEL_NOTIFICATION_KEY = 'NEW_NOTIFICATION';// Create BroadcastChannel for notificationconst notificationChannel = new BroadcastChannel(storageKey);// Must be placed before importScriptsglobalThis.addEventListener('notificationclick', (event) => { logger('[notificationclick]', event); if (!event.notification || !event.notification.data) { return; } event.notification.close(); const { FCM_MSG } = event.notification.data; if (!FCM_MSG) { return; } const { data } = FCM_MSG; const defaultLink = globalThis.location.origin; const link = data?.link || defaultLink; event.waitUntil( clients.matchAll({ type: 'window', includeUncontrolled: true }).then((windowClients) => { for (const client of windowClients) { const clientUrl = new URL(client.url); const notificationUrl = new URL(link); if (clientUrl.origin === notificationUrl.origin && 'focus' in client) { client.postMessage({ [searchKey]: searchValue }); return client.focus(); } } return clients.openWindow(`${link}?${searchKey}=${searchValue}`); }), );});importScripts('https://www.gstatic.com/firebasejs/10.13.2/firebase-app-compat.js');importScripts('https://www.gstatic.com/firebasejs/10.13.2/firebase-messaging-compat.js');importScripts('https://cdnjs.cloudflare.com/ajax/libs/idb-keyval/6.2.2/umd.js');const firebaseConfig = { apiKey: 'AIzaSyCN99e2MFNFCBgZAh4YjbboM7dx4L208cc', authDomain: 'my-awesome-20250904.firebaseapp.com', projectId: 'my-awesome-20250904', storageBucket: 'my-awesome-20250904.firebasestorage.app', messagingSenderId: '447700238822', appId: '1:447700238822:web:57170ca06a374c10671627', measurementId: 'G-L0TVC48MM3',};// Initialize the Firebase app in the service worker by passing in// your app's Firebase config object.// https://firebase.google.com/docs/web/setup#config-objectfirebase.initializeApp(firebaseConfig);// Retrieve an instance of Firebase Messaging so that it can handle background// messages.const messaging = firebase.messaging();messaging.onBackgroundMessage(async (payload) => { logger('[firebase-messaging-sw.js] Received background message:', payload); // Store message to IndexedDB try { // Get existing data, keep Zustand's StorageValue structure const existingData = (await idbKeyval.get(storageKey)) || { state: { notifications: [], }, version: 0, }; const newNotification = { ...payload, createdAt: Date.now(), }; existingData.state.notifications = [newNotification, ...existingData.state.notifications]; existingData.version = existingData.version || 0; await idbKeyval.set(storageKey, existingData); // 通过 BroadcastChannel 通知所有打开的页面同步数据 notificationChannel.postMessage({ type: CHANNEL_NOTIFICATION_KEY, payload, }); } catch (_error) {}});API Reference
FCM (Firebase Cloud Messaging) 工具库提供了一套完整的函数和 React Hook,用于在 Web 应用中集成 Firebase 推送通知功能。
Git Commit History(1 commits)
feat: build
Marvin
11月14日 03:30
e50053c2