service worker 可作为性能埋点的中转站与缓冲层,通过拦截请求、暂存 indexeddb、混合触发批量上报(定时/可见性变化/阈值)、keepalive 保活及 sync 重试机制,实现可靠离线采集与上报。

Service Worker 可以作为前端性能埋点的“中转站”和“缓冲层”,在不干扰主线程、不加重页面负担的前提下,实现请求拦截、数据聚合、离线缓存与批量上报。关键不在“能不能做”,而在于如何设计上报时机、合并逻辑和失败重试机制。
为什么用 Service Worker 做性能埋点上报
传统页面内埋点(如直接调用 fetch 或 Image 上报)存在几个硬伤:主线程阻塞风险、弱网下丢包率高、页面卸载时请求被中断、无法统一控制上报策略。Service Worker 独立运行、可持久驻留、能监听 fetch 和生命周期事件,天然适合承担“可靠信使”角色——尤其对 FCP、LCP、CLS、FID 这类 Web Vitals 指标,以及资源加载耗时、长任务、导航阶段等底层性能数据。
拦截性能数据并暂存到 IndexedDB
页面脚本采集到性能条目后,不立即发送,而是通过 postMessage 发送给 Service Worker:
PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
- 页面端示例:
navigator.serviceWorker.controller?.postMessage({
type: 'PERF_EVENT',
payload: { name: 'largest-contentful-paint', startTime: 1245.3, duration: 12.7 }
 }); - Service Worker 端监听并写入 IndexedDB(推荐使用
idb库简化操作):
self.addEventListener('message', async (event) => {
if (event.data.type === 'PERF_EVENT') {
const db = await openDB('perfDB', 1);
await db.add('events', { ...event.data.payload, ts: Date.now() });
}
 }); - IndexedDB 比 localStorage 更可靠:支持结构化数据、事务、大容量存储,且不受页面关闭影响。
按条件触发批量上报
上报不能“来一条发一条”,也不能“等到页面关了才发”。合理策略是混合触发:
-
定时上报:每 10 秒检查一次 DB 中未上报条目,合并为单个 POST 请求(例如封装成
{events: [...], sessionId: 'xxx'}); -
页面可见性变化:监听
visibilitychange事件,当页面切到后台或即将卸载(pagehide),立刻触发一次强制上报; - 队列阈值触发:当待上报条目 ≥ 20 条,立即打包发送,避免延迟过久;
- 所有上报请求都带上
keepalive: true,确保即使页面已关闭,请求仍能发出。
失败重试 + 离线兜底
网络不可靠是常态。Service Worker 需内置容错逻辑:
- 上报失败(HTTP 非 2xx、超时、网络断开)时,将原始 payload 标记为
status: 'pending'并保留在 DB 中; - 利用
sync事件实现后台重试(需注册syncpermission):
self.addEventListener('sync', async (event) => {
if (event.tag === 'perf-upload') {
event.waitUntil(attemptUpload());
}
 }); - 定期清理过期数据(如 24 小时前的 pending 条目),防止 DB 膨胀;
- 若用户长期离线,DB 中积压数据最多保留 7 天,之后自动丢弃,平衡可靠性与存储压力。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










