PWA中Push API收不到推送消息是怎么回事?

苗苗 阅读 234

我在做PWA的推送功能,已经成功注册了service worker,也拿到了用户的订阅信息,但调用后端发送推送后,手机上完全没反应。

我试过在Chrome DevTools里手动触发push事件,能收到,但真实从服务器发就不行。是不是VAPID配置有问题?或者需要HTTPS?

后端用的是Node.js,推送时返回状态码是201,看起来成功了,但前端就是没触发self.addEventListener('push')这个监听。

我来解答 赞 10 收藏
二维码
手机扫码查看
2 条解答
梓熙 Dev
最常见的问题是后端加密没做好。后端发推送时需要对payload加密,用的VAPID私钥必须和前端订阅时用的公钥是一对。

检查一下你后端代码是不是这样写的:

const webpush = require('webpush');

const vapidKeys = {
publicKey: '你的公钥(和前端subscription时用的一样)',
privateKey: '你的私钥'
};

webpush.setVapidDetails(
'mailto:your@email.com',
vapidKeys.publicKey,
vapidKeys.privateKey
);

// 发送推送
webpush.sendNotification(
subscription, // 就是前端传过来的subscription对象
JSON.stringify({ title: '测试', body: '消息内容' })
).catch(err => console.error(err));


如果公钥不一致或者加密方式不对,FCM虽然返回201但设备根本收不到。

另外确认一下subscription对象里的endpoint是不是FCM的URL(以fcm.googleapis.com结尾),如果是的话会有几秒到几分钟的延迟,多等等。
点赞
2026-03-13 04:01
洛熙 ☘︎
这个推送问题我遇到过太多次了,让我帮你捋一下。首先HTTPS是必须的,但不是你问题的原因,因为你说DevTools手动触发能收到。

VAPID配置确实是最常见的坑点,特别是这几个地方容易出错:
1. 检查你的公钥私钥有没有搞混,后端推送时必须用VAPID私钥签名
2. 确保订阅对象里的endpoint是正确的FCM地址
3. 后端推送时headers里必须包含Authorization和Crypto-Key

给你个Node.js推送的示例代码:
const webpush = require('web-push');
webpush.setVapidDetails(
'mailto:your@email.com',
'公钥',
'私钥'
);

webpush.sendNotification(subscription, payload)
.catch(err => console.error('推送失败:', err.statusCode, err.body));


另外检查下手机端的通知权限有没有被关闭,有些手机会默认阻止后台推送。建议先用console.log在service worker里打印推送事件,确认到底有没有触发。

如果还不行,把后端推送时的完整请求和响应贴出来看看,重点检查返回的201是真实成功还是假成功。
点赞 1
2026-03-09 20:45