开放问答
Service Worker 缓存旧 bundle 导致 sourcemap 版本错位:堆栈映射到错误 release 怎么根治?
该问题的正文、回答与评论。
提问者 顾砚舟-904 · 状态 open
前端Service Workersourcemap可观测性错误监控
【背景】 React 18 + Vite 5 的 B 端中台,约 200 个路由,用 Workbox 做 Service Worker 预缓存(precacheManifest 约 380 个资源)。错误上报走 Sentry,sourcemap 按 release 版本号(semver)上传,Sentry 侧按 release 字段匹配对应 sourcemap 做堆栈还原。
【现象】 每次发版后 24–72 小时内,Sentry 里会稳定出现一批"堆栈完全对不上"的错误:
- release 字段是旧版本(如 v2.31.0),但旧版 sourcemap 在发版后第 7 天就被清理策略删掉了;
- 堆栈里出现
at e (app.3f2a.9c1d.js:1:88234)这类纯压缩帧,无法还原; - 同一错误指纹在不同 release 下被拆成多条 issue,告警重复触发,一周内误报约 14 次。
用 navigator.serviceWorker.controller.scriptURL 排查,确认约 8%–12% 的活跃用户仍在使用旧版 SW 缓存的 bundle(尤其是 Android 低版本 Chrome 和 iOS Safari 15)。
【已尝试的排查与结果】
- SW activate 阶段
self.clients.claim()+ 遍历caches.keys()删旧缓存:能清掉缓存,但已有 tab 里加载的旧 JS 模块仍然在执行,错误仍会打到旧 release 上。 - 上报 SDK 里附带
navigator.serviceWorker.controller.scriptURL和document.currentScript.src做双字段上报:能区分"用户实际跑的是哪个 bundle",但 Sentry 的 release 字段只有一个,无法按 bundle 粒度匹配 sourcemap,等于多了一个字段但没解决问题。 - 把 sourcemap 保留期从 7 天拉长到 30 天:缓解了一部分,但存储成本翻了 4 倍,且 30 天后的老版本仍然会漏。
- Workbox 的
revision策略改为 hash-based(而非 time-based):新 bundle 文件名变了,理论上旧 SW 的 precacheManifest 不会命中新文件——但实测发现部分用户 SW 根本没触发 updatefound,旧 manifest 一直生效。
【期望得到的答案形态】
- 一个可落地的方案(代码 / 配置级别),让"用户实际运行的 bundle 版本"与"上报的 release 字段"强一致,从而 sourcemap 匹配不再错位;
- 对 SW 更新检测失败(updatefound 不触发)的根因分析和兜底策略(比如
registration.update()的调用时机、skipWaiting与clients.claim的取舍); - 如果业界有"放弃 SW 预缓存、改用 CDN + Cache-Control"的迁移经验,也欢迎分享迁移步骤和踩坑。
我倾向用具体数字和配置说话,所以如果方便,请带上你项目的 Workbox / Sentry 配置片段或关键参数。
已采纳
回答者
回答正文
评论
暂无评论。