shared worker 是唯一能跨标签页、iframe 和多窗口统一协调前端埋点的机制,通过集中调度、状态感知与生命周期联动实现合理批量上报,避免重复、丢失与无效请求。

Shared Worker 是目前唯一能跨标签页、iframe 和多窗口统一协调前端埋点行为的机制。它不直接“排空队列”,而是通过集中调度、状态感知与生命周期联动,让埋点数据在最合理的时间点批量发出,既避免重复上报、丢失关键事件,又减少无效请求和后台耗电。
为什么不能每个页面自己 flush 埋点队列
埋点队列通常缓存用户行为(如点击、停留、曝光),等待合适时机批量上报。若每个页面独立 flush:
- 同一用户打开 5 个标签页,可能在 1 秒内触发 5 次相同事件(如“首页曝光”)的重复上报
- 页面切后台时,主线程定时器被冻结或大幅降频,导致埋点积压甚至永久丢失
- 页面意外崩溃或强制关闭,未 flush 的数据彻底消失,无兜底机制
- 多个页面同时 flush,易触发服务端限流或写入抖动
Shared Worker 如何接管埋点排空逻辑
核心思路是:把“何时发”从页面侧上收,由 Shared Worker 统一判断上下文状态,并按策略触发 flush。
前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。
-
页面只负责投递:各页面调用
port.postMessage({ type: "track", event: {...} }),Worker 将事件暂存至 Map,不立即发送 -
监听可见性变化:Shared Worker 无法直接访问 document,但可通过页面广播告知 visibility 状态 —— 页面监听
document.visibilityState,切到 hidden 时广播{ type: "visibility", state: "hidden" },Worker 收到后触发一次 flush -
绑定页面生命周期:页面卸载前(
beforeunload或pagehide)主动发{ type: "flush-now", reason: "page-close" },Worker 立即合并当前 clientId 下所有事件并上报 - 设置静默超时兜底:Worker 内维护每个 clientId 的最后活跃时间戳,若 15 秒内无新事件且无 visibility 变化,则自动 flush,防止长期积压
关键细节与容错设计
排空不是简单“清空数组”,而是一次带语义的聚合动作:
- 上报前对同类型事件去重(如连续 3 次“按钮点击”可合并为 count=3)
- 携带统一 traceId 与 clientId,便于服务端识别是否来自同一用户多视窗会话
- 失败时本地暂存(可用 IndexedDB 或 localStorage),待下次联网或页面激活时重试
- Worker 自身关闭前(最后一个同源页面关闭),遍历所有 clientId 的缓存,执行最终 flush
兼容性与降级路径
Safari 16.3 及更早版本不支持 Shared Worker,需 fallback:
- 检测
typeof SharedWorker === 'function',不可用时启用 BroadcastChannel + 主控页模式 - 首个激活页面成为主控页,负责监听 visibility 和页面卸载,并通过 BroadcastChannel 广播 flush 指令
- 其他页面只接收指令、提交本地队列,不主动触发 flush
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










