Service Worker 的 push 事件监听必须在顶层作用域注册,即直接写在 sw.js 文件最外层,不可包裹在 install/activate 回调、函数或异步逻辑中,否则浏览器无法识别并触发该事件。

Service Worker 的 push 事件监听必须在顶层作用域注册
浏览器只会在 Service Worker 脚本的最外层(即非函数、非条件块内)执行 self.addEventListener('push', ...) 时,才将其识别为有效的推送事件处理器。如果把它写在 self.addEventListener('install', ...) 回调里,或封装成函数再调用,事件根本不会触发。
- 必须直接写在 SW 文件顶部作用域,不能包裹在
if、function或异步回调中 - 确保没有语法错误或未捕获的异常——SW 启动失败会导致整个
push监听器静默失效 - Chrome DevTools 的 Application → Service Workers 面板里,点击 “Update on reload” 并刷新页面,可强制重载 SW 并查看控制台是否报错
push 事件中不能直接操作 DOM,只能发通知或写缓存
push 事件运行在独立线程(Service Worker 环境),没有 window、document 或 alert()。常见错误是试图在里面调用 fetch() 后更新页面元素,这会抛出 ReferenceError: document is not defined。
- 能做的只有三类操作:调用
self.registration.showNotification()、调用self.clients.matchAll()获取已打开页面并postMessage、用cache.put()预存资源 - 如果需要页面响应,得用
self.clients.matchAll().then(clients => clients.forEach(c => c.postMessage(...))),再在页面 JS 中监听navigator.serviceWorker.addEventListener('message', ...) - 注意
showNotification()的data字段必须是可序列化的对象(不能含函数、Date、RegExp 等),否则通知无法显示
后端发送 VAPID 推送前必须校验 subscription 和密钥格式
浏览器生成的 subscription 是个对象,含 endpoint、keys.p256dh、keys.auth。后端若直接把整个对象 JSON.stringify 后发给推送服务(如 WebPush),大概率返回 400 Bad Request 或 401 Unauthorized。
-
endpoint必须是完整 HTTPS URL(不能以/push结尾,也不能缺协议) -
keys.p256dh和keys.auth必须是 base64url 编码(不是标准 base64),且无填充字符(=)、无换行;Node.js 可用crypto.createPublicKey(...).export({ format: 'jwk', ... })辅助验证 - VAPID 公钥需提前通过
navigator.serviceWorker.register()时传入applicationServerKey注册,私钥绝不能泄露到前端
调试 push 事件最有效的三个检查点
本地测试时,90% 的“收不到推送”问题集中在以下三处,按顺序排查比反复改代码更快。
立即学习“前端免费学习笔记(深入)”;
- 在 Chrome 地址栏输入
chrome://serviceworker-internals/,确认你的 SW 已激活(Active)且状态为 “Waiting” 或 “Running”,右键 “Unregister” 后刷新重装 - 在 SW 文件里加
self.addEventListener('push', e => { console.log('push received:', e.data?.json()); e.waitUntil(Promise.resolve()); });,然后用cURL模拟推送,看控制台是否有日志 - 检查浏览器设置:地址栏输入
chrome://settings/content/notifications,确认你的域名有通知权限;若用 localhost,需启用chrome://flags/#unsafely-treat-insecure-origin-as-secure


















