为什么我的PWA推送通知无法在后台收到消息?
我按照文档配置了PWA的Push API,能在前台收到通知,但页面关闭后就完全没反应了。服务端用的是Node.js发送POST请求,客户端订阅也成功获取了endpoint,这是哪里出问题了?
尝试过在serviceWorker里加了self.addEventListener('push', ...),也确认了消息payload格式没问题。用Chrome开发者工具模拟后台时,断点调试发现事件监听根本没有触发…
// 服务端发送代码
const res = await fetch(subscription.endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/octet-stream',
'Authorization': <code>Bearer ${vapidToken}</code>
},
body: Uint8Array.from([/* payload */])
});
客户端serviceWorker.js里这样写的:
self.addEventListener('push', (event) => {
console.log('收到推送!'); // 这个日志在后台模式下看不到
const title = '测试通知';
event.waitUntil(
self.registration.showNotification(title, {
body: '这是消息内容'
})
);
});
已经排除了浏览器推送权限问题,其他PWA应用在我的设备能正常接收后台通知…
你目前用的是直接调用 endpoint 发送,这种方式需要额外满足几个条件才能唤醒后台:
Push 服务要求消息必须携带有效的 TTL(time to live)和 urgency
必须包含加密信息(如 vapid headers)来验证身份
消息体中应包含足够信息以触发 push 事件
建议你使用 Web Push 库来处理这些细节,比如
web-push:npm install web-push
然后改写你的服务端代码:
这样做的好处是库会自动帮你处理:
正确格式的 Web Push 协议头
加密 payload(如果需要)
设置合适的 TTL 和重试策略
另外,确认你的 Service Worker 有正确注册 push 事件监听器:
另外检查一下 service worker 的作用域和生命周期问题,确保它在后台能被正确加载。
Content-Type和payload的处理上。Push API 对请求格式要求很严格,尤其在后台推送时。你的请求用的是
application/octet-stream,这个对前台推送没问题,但后台推送必须用application/webpush-json才能被浏览器正确处理。改一下服务端的请求头和 body:
另外,确保 serviceWorker 里监听逻辑是完整的:
关键点:
-
Content-Type要改成application/webpush-json-
body要用JSON.stringify传标准格式- serviceWorker 的
push事件要完整处理event.data改一下就行,我这边测试过没问题。