SharedWorker是浏览器提供的多页面共享后台线程机制,允许多个同源标签页、iframe等共用同一实例,实现可控、实时的跨标签页通信与状态同步。

SharedWorker 是浏览器提供的一个 Web Worker 类型,能让多个同源的浏览器上下文(比如多个标签页、iframe 或其他 SharedWorker 实例)共享同一个 Worker 线程,从而实现跨标签页通信。它比 localStorage + storage 事件或 BroadcastChannel 更可控、更实时,也比 postMessage 配合 iframe 绕行更规范。
一、SharedWorker 的基本使用流程
要让多个页面共用一个 SharedWorker,需确保它们加载的是**同一份 JS 脚本**(URL 完全一致,包括协议、域名、路径、查询参数),且同源。
- 在每个页面中通过
new SharedWorker('worker.js')创建实例,返回一个port对象 - 必须显式调用
port.start()(尤其在 addEventListener 用箭头函数时容易遗漏) - 通过
port.postMessage(data)发送消息,用port.onmessage接收来自 Worker 或其他页面的消息 - Worker 脚本中监听
connect事件,拿到 port 后调用port.start()并绑定消息处理逻辑
二、一个可运行的跨标签页计数器示例
假设你有两个标签页都打开 http://localhost:3000/index.html:
前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。
页面代码(index.html):
立即学习“前端免费学习笔记(深入)”;
<button id="inc">+1</button>
<span id="count">0</span>
<script>
const worker = new SharedWorker('counter-worker.js');
const port = worker.port;
port.onmessage = ({ data }) => {
document.getElementById('count').textContent = data.count;
};
port.start(); // 关键:不调用则不会触发 connect 事件
document.getElementById('inc').onclick = () => {
port.postMessage({ type: 'increment' });
};
</script>
Worker 脚本(counter-worker.js):
let count = 0;
const ports = [];
self.onconnect = function(e) {
const port = e.ports[0];
ports.push(port);
port.onmessage = function({ data }) {
if (data.type === 'increment') {
count++;
// 广播给所有连接的页面
ports.forEach(p => p.postMessage({ count }));
}
};
port.start();
};
三、需要注意的关键细节
-
同源限制严格:即使端口不同(如
http://localhost:3000和http://localhost:8080)也不共享;HTTPS 和 HTTP 视为不同源 -
Worker 脚本不能访问 DOM 或 window,只能操作全局作用域(
self)、定时器、fetch、IndexedDB 等受限 API - 页面关闭时 port 自动断开,但 Worker 进程可能继续运行(直到所有 port 断开后约几秒才销毁),适合做轻量状态聚合
-
错误需在 Worker 内捕获:在 worker 脚本中加
self.onerror = console.error,否则静默失败 - 调试技巧:Chrome DevTools → Application → Shared Workers 可查看当前活跃的 SharedWorker 及其连接数
四、SharedWorker vs 其他跨页通信方案对比
- BroadcastChannel:API 更简单,支持字符串/结构化克隆数据,但不兼容 IE 和旧版 Safari;无法直接与 Worker 通信
- localStorage + storage 事件:兼容性最好,但只在值变化时触发,且无法传递函数、undefined、Symbol 等;事件不保证顺序
- Service Worker + postMessage:适合离线/拦截请求场景,但需要注册 SW,复杂度高;不是为多页状态同步设计
- SharedWorker 优势:有独立执行线程、可维护共享状态、支持复杂逻辑和异步任务(如轮询、缓存合并),适合中等复杂度的协同场景

















