FCM本地运行正常但生产环境无法发送通知问题求助
问题描述
我在Web应用中使用FCM实现通知功能,本地环境下可以正常收发通知,但部署到Vercel生产环境后,仅能接收来自Firebase控制台、Postman等渠道的通知,无法通过应用内的API主动发送通知。
具体情况:
- 使用Vercel托管服务及Vercel API路由
- 本地与Vercel配置了相同的环境变量
- 浏览器端调用API路由均返回200成功响应,但通知无法送达
- Vercel未显示服务端日志,无法调试
附上Next.js应用中API/send路由的代码:
import { NextResponse } from 'next/server' import { getFirestore } from 'firebase-admin/firestore' import { initAdmin } from '@/db/firebaseAdmin' import { getMessaging } from 'firebase-admin/messaging'; export async function GET (req: Request, res: Response) { // Initialize Firebase Admin const app = await initAdmin(); // get current time const currentTime = new Date(); try { const registrationTokens = [ 'f3QNNQiLrpA4n1ayL46sz6:APA91bE-Zy9ypgl6R9nmBKYc_KgrhZs6sD3NqzEG6pLIsaGEQF2wrPSZpO-MWwanAnP0eHUGmCy2PqesD7ZR3IWNO1uumO3-KAvcjMqFWZ3aFpzaoUGa9UKSUtSP3Zgj0LpePuPluf4T', // mobile 'fWRzguAj87BidFhkNCRdUP:APA91bEfsz8d8XSPW3SOG862V968wvn3vOhu_eJiIG2pGp4a_MrwzUUapzNg8BKvoMuF2FXqFo1f0-YlKjJSqnyf7Y_YfhbTFB8X-PsxcHJ2oOHtUAa-aQHsZg9AK5LcQqOrir9k4X56', // localhost 'faggSiQojS1TTnljfWE1R7:APA91bHTSLOpEykD75JB_0pyqAautPijFyeLXebor8nVguBHxmvj-eMJzYe6PW51sOoPK4KzAJJlHPc9x-jcFyRurggvXhSFzF8jPtJYfog4RCQSMC1Mi12bRgamCBhSdGz5Rcmhkya9' // deployed desktop ]; const message = { notification: { title: currentTime.toString(), body: "message" } }; // Initialize Messaging const messaging = getMessaging(app); // Send a message to the devices corresponding to the provided registration tokens. const sendPromises = registrationTokens.map(token => { return messaging.send({ ...message, token: token }); }); // Use Promise.all to wait for all messages to be sent const responses = await Promise.all(sendPromises); console.log('Successfully sent messages:', responses); return NextResponse.json({ message: "Notifications sent", responses: responses }); } catch (error: any) { console.error('An error occurred while sending notifications:', error); return NextResponse.json( { message: error.message || 'Internal Server Error' }, { status: 500 } ); } }
可能的原因及解决办法
1. Firebase Admin初始化异常
- 检查
initAdmin()函数在生产环境的密钥加载逻辑:Vercel环境变量中存储JSON格式密钥时,容易出现转义错误,建议直接粘贴密钥内容(不要加外层引号),或者将密钥Base64编码后存储,在代码中解码使用。 - 避免重复初始化App实例,修改
initAdmin()添加判断:if (getApps().length === 0) { initializeAdminApp(...) }
2. 通知格式不符合生产环境要求
- FCM生产环境对Web通知的格式要求更严格,仅提供
notification字段可能无法触发显示。补充webpush配置:const message = { notification: { title: currentTime.toString(), body: "message" }, webpush: { notification: { requireInteraction: true, icon: "/your-app-icon.png" } } };
3. Vercel日志无法查看的临时解决
- Vercel API路由日志需在控制台「Functions」页面找到对应函数查看。如果仍无法获取日志,临时修改catch块返回错误详情到前端:
return NextResponse.json( { message: error.message || 'Internal Server Error', errorStack: error.stack // 调试完成后移除 }, { status: 500 } );
4. 注册令牌失效
- 生产环境设备令牌可能因域名、HTTPS配置变更失效,前端需添加令牌刷新逻辑,发送通知时单独处理每个令牌的错误:
const sendPromises = registrationTokens.map(async token => { try { return await messaging.send({ ...message, token }); } catch (err) { console.error(`Failed to send to ${token}:`, err); // 这里可添加令牌失效后的数据库清理逻辑 return `Failed: ${err.message}`; } });
5. Vercel函数执行限制
- Vercel免费版函数最长执行时间为10秒,批量发送通知可能超时。建议拆分令牌批次发送,或改用Vercel Edge Functions提升执行效率。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

