sharedworker 是浏览器原生支持的跨标签页通信机制,让同源多个页面共享同一后台线程,实现状态共用与逻辑协同;需独立脚本、同源前提、手动启端口、手动维护状态、生命周期独立,并受 dom 操作限制及 https/safari 兼容性约束。

SharedWorker 是浏览器原生支持的跨标签页通信机制,它让同源下的多个页面、iframe 或窗口共享同一个后台线程,从而实现真正的状态共用与逻辑协同。它不是简单的消息中转站,而是一个可长期驻留、带状态、能统一调度的轻量级“前端服务端”。
SharedWorker 的核心实现要点
要真正用好 SharedWorker,得抓住几个不可绕开的技术细节:
-
必须部署独立脚本文件:不能写成内联 script,必须是单独的 .js 文件(如
shared-worker.js),通过new SharedWorker('shared-worker.js')加载 -
同源是硬性前提:协议、域名、端口三者完全一致才可连接;
http://localhost:3000和https://localhost:3000视为不同源 -
端口需手动启动:页面侧调用
worker.port.start(),Worker 侧在onconnect中对每个 port 调用port.start(),否则消息通道不激活 -
状态靠手动维护:Worker 内部的全局变量(如
let counter = 0、const cache = new Map())天然被所有连接共享,但无锁机制,高并发时需加判断或标记位防竞态 - 生命周期独立于页面:只要还有一个页面保持连接,Worker 就持续运行;所有连接断开后,若无定时器或未关闭的 fetch/IndexedDB 事务,浏览器才会回收
典型应用场景与对应做法
SharedWorker 不适合替代 localStorage 做简单键值存储,它的价值在于需要“统一执行逻辑”的协同场景:
-
登录态与权限同步:一个标签页登出时,SharedWorker 收到
{ type: 'logout' }消息,立即遍历当前所有 port 广播通知,各页面据此清空本地 token、跳转登录页 -
避免重复请求的 API 代理:多个标签页同时请求用户配置,SharedWorker 检查缓存是否存在;若无,则发起一次
fetch,成功后缓存并广播结果给所有等待中的 port - 实时协作状态管理:如文档编辑场景,各页面上报“进入编辑”“离开编辑”,SharedWorker 维护在线编辑人数、最后活跃时间,并定时广播最新状态
- 统一 WebSocket 连接管理:SharedWorker 建立并维持单个长连接,所有页面通过它收发消息;页面关闭不影响连接存活,新页面接入后自动同步上下文
使用时必须注意的限制与兼容性
SharedWorker 功能强大,但也有明确边界,忽略这些容易踩坑:
-
不支持 DOM 操作:不能访问
window、document、localStorage等浏览器 API,只能用fetch、IndexedDB、setTimeout等 Web Worker 可用接口 -
HTTPS 或 localhost 才可用:非安全上下文(如普通 http)下会被浏览器拒绝,开发阶段可用
localhost,生产环境必须 HTTPS -
Safari 支持较晚:16.4 版本起才完整支持,旧版 Safari 会静默失败,建议做
if ('SharedWorker' in window)检测并降级处理 - 无法直接传递函数或 DOM 节点:postMessage 只支持结构化克隆,复杂对象需序列化或拆解为纯数据字段
与 BroadcastChannel、localStorage 的关键区别
它们都能跨标签页通信,但定位完全不同:
- BroadcastChannel:只负责广播消息,无状态、无逻辑,适合“通知类”动作(如“刷新缓存”),但无法保存当前有多少人在线
- localStorage + storage 事件:能持久化,但仅限字符串,且写入是异步的,多个页面并发写可能覆盖;storage 事件也无法保证顺序或送达
- SharedWorker:有状态、可计算、可协调——它能记住谁连着、谁刚断开、当前总人数、上次请求结果是什么,还能主动发起网络请求或数据库操作











