Service Worker 与主页面通信必须通过 postMessage,且需确保 navigator.serviceWorker.ready 就绪后再发送;SW 端用 self.addEventListener('message') 监听并用 event.source.postMessage() 回复;消息体须可序列化,避免在 message 回调中执行耗时操作。

Service Worker 和主页面之间不能直接调用函数或读写变量,必须走 postMessage 通信。不理解这点,就容易卡在“worker 收不到消息”或“页面收不到 reply”上。
主页面怎么发消息给 Service Worker
必须等 navigator.serviceWorker.ready 解析完成,才能安全调用 registration.active.postMessage() 或 registration.waiting.postMessage()。直接在注册后立刻发,大概率失败。
-
navigator.serviceWorker.register('/sw.js')只是启动注册,不等于 ready - 推荐用
navigator.serviceWorker.ready.then(reg => reg.active?.postMessage(...)),避免访问null - 消息体只能是可序列化的值(plain object、string、number),不能传 function、DOM 节点、
Promise等 - 如果 SW 还没激活(比如刚更新、处于
waiting状态),要手动触发skipWaiting(),否则active为undefined
Service Worker 怎么监听并响应页面消息
self.addEventListener('message', ...) 是唯一入口,但要注意:它只收主页面(或其它 worker)发来的 postMessage,不收 push 事件、fetch 事件或定时事件。
- 必须在 SW 文件顶层监听,不能包在
install或activate事件里 - 回复页面时,要用
event.source.postMessage(),不是self.postMessage() - 如果想广播给所有客户端(比如多个标签页),得遍历
self.clients.matchAll()后逐个postMessage - 别在 message 回调里做耗时操作(如大量计算、未加锁的 IndexedDB 写入),会阻塞其他消息
为什么页面收不到 Service Worker 的回复
最常见原因是没正确绑定 message 监听器,或监听时机太晚——比如在 serviceWorker.ready 之前就加了 window.addEventListener('message', ...),而 SW 已经发完 reply 了。
立即学习“前端免费学习笔记(深入)”;
- 主页面监听应写在
navigator.serviceWorker.register().then(...)之后,或用navigator.serviceWorker.addEventListener('message', ...) -
event.data是纯数据,没有类型信息;前后端约定好结构,比如统一用{ type: 'sync_done', payload: ... } - Chrome DevTools 的 Application → Service Workers 面板里勾选 “Update on reload” 和 “Offline”,能强制刷新并暴露通信断点
- 如果用
clients.claim(),新 SW 会立即接管已有页面,但旧页面的 message 监听器可能还没挂载,造成“丢失首条消息”
push 事件和 message 事件完全不混用
很多人以为 self.addEventListener('push', ...) 能收到页面发的消息,其实不能。push 只响应服务器通过 Web Push 协议下发的加密消息;message 才是页面主动发起的通信通道。
- 混淆两者会导致:页面调
postMessage,SW 却在push里等,永远不触发 - Web Push 的 endpoint 是一次性 URL,每次订阅都变;而
postMessage是运行时通道,不依赖后端、不需 VAPID、也不受 iOS Safari 限制 - 需要持久广播(如多标签页同步状态),优先用
BroadcastChannel;仅需单向控制(如让 SW 清缓存),用postMessage更轻量
真正难的不是写通通信逻辑,而是理清生命周期:页面加载 → SW 注册 → ready → 激活 → 页面监听 message → SW 监听 message → 双向确认。任一环节异步时机没卡准,消息就掉进黑洞里。



















