sharedworker 是同源多页面共享的单例后台线程,通过端口机制实现双向通信与消息广播,依赖同源、外置脚本及https/localhost环境,用于登录态同步、请求去重和websocket统一管理。

SharedWorker 是浏览器原生提供的、能在同源多个页面(标签页、iframe、窗口)间共享的后台线程,它不是每个页面各起一个线程,而是**所有同源页面共用同一个运行实例**,天然具备状态共享能力。
SharedWorker 的核心原理
浏览器内核对 SharedWorker 实行“单例管理”:只要脚本 URL、协议、域名、端口、name(可选)完全一致,无论多少个页面调用 new SharedWorker('./shared-worker.js'),最终都连接到**同一个底层线程实例**。这个实例拥有独立的全局作用域(SharedWorkerGlobalScope),其内部变量(如 let count = 0、const cache = new Map())被所有连接页面共同读写——这才是多标签页共享数据的根本来源,而非靠消息转发或外部存储中转。
为什么能跨标签页实时同步
关键在于通信模型和生命周期设计:
-
端口(Port)机制:每个页面通过
worker.port与 SharedWorker 建立双向通信通道;Worker 收到连接后,在onconnect回调中拿到event.ports[0],并需主动调用port.start()激活通道 - 状态驻留不依赖页面:SharedWorker 生命周期独立于任何单个页面——只要还有一个页面保持连接,线程就持续运行;所有页面关闭后,若无未清除的定时器或活跃资源(如 WebSocket、fetch 请求),浏览器才回收它
-
消息广播由 Worker 主动发起:比如一个页面发来登出指令,SharedWorker 可遍历当前所有已存 port,逐个
port.postMessage()通知,其他页面监听到即响应,实现秒级同步
必须满足的前提条件
SharedWorker 不是“开箱即用”,以下三点缺一不可:
-
同源强制校验:协议(http/https)、主机名、端口号三者必须完全相同;
http://localhost:3000和https://localhost:3000视为不同源,无法共享 -
脚本必须外置:不能使用内联
<script></script>,必须是独立可访问的 JS 文件(如/shared-worker.js),且路径在所有页面中解析结果一致 -
HTTPS 或本地环境:现代浏览器(尤其 Safari)要求 SharedWorker 必须运行在 HTTPS 或
localhost下,HTTP 非本地环境将直接报错
典型共享场景举例
它不是 localStorage 替代品,而是解决“协同逻辑统一执行”的问题:
- 用户登录态管理:一个标签页登出 → SharedWorker 清空 token 缓存 + 广播 logout 消息 → 其他页面自动跳转登录页
- API 请求去重:多个标签页同时请求用户配置 → SharedWorker 检查内存缓存 → 仅发起一次 fetch → 成功后广播结果给全部等待中的页面
- WebSocket 统一连接:SharedWorker 创建并维持唯一长连接 → 所有页面通过它收发消息 → 页面关闭不影响连接存活,新页面接入即同步上下文











