service worker 更新失败主因是强缓存导致字节内容未变,必须通过动态注释、哈希路径、禁用强缓存响应头(如cache-control: no-cache)、register时设updateviacache: 'none'等手段确保每次加载内容唯一。

Service Worker 脚本(如 sw.js)更新失败,最常见的原因就是浏览器或 CDN 对它做了强缓存,导致即使你部署了新版本,浏览器仍加载旧的字节内容——而 Service Worker 的更新机制只在脚本内容**字节不同**时才触发。所以防强缓存不是“可选项”,而是更新生效的前提。
确保每次部署 SW 脚本内容唯一
浏览器判断 SW 是否有更新,依据是下载到的脚本文件是否与已注册版本存在字节差异。哪怕只多一个空格、一行注释、一个时间戳,都算“新版本”。
- 开发阶段:在
sw.js文件末尾添加动态注释,例如// build: 20261008-1414,配合构建工具自动注入当前时间戳 - 上线阶段:避免用固定路径直接引用
/sw.js,改用带哈希或版本号的路径,如/sw.9a2b3c.js或/sw.js?v=2.1.0 - 不推荐仅靠
location.reload()强刷来“碰运气”,这无法解决缓存未失效的根本问题
服务端禁用 SW 脚本的强缓存
HTTP 响应头对 SW 脚本的缓存控制至关重要。不能依赖 Cache-Control: max-age=3600 这类长缓存策略,必须让浏览器每次请求都向服务器验证或直接获取最新内容。
- 推荐响应头:
Cache-Control: no-cache, must-revalidate—— 强制每次请求都走协商缓存(如带ETag或Last-Modified) - 更严格可选:
Cache-Control: no-store(完全禁止缓存)或Cache-Control: max-age=0,但需注意 CDN 可能忽略no-store - 确保 Webpack/Vite 等构建工具不给
sw.js自动加哈希后缀的同时又配置了强缓存;二者逻辑要统一
注册时主动绕过浏览器缓存
调用 navigator.serviceWorker.register() 时,可以传入 { updateViaCache: 'none' } 选项(Chrome 93+、Firefox 99+ 支持),明确告诉浏览器不要从 HTTP 缓存中读取 SW 脚本。
- 示例:
navigator.serviceWorker.register('/sw.js', { updateViaCache: 'none' }) - 该选项仅影响本次注册请求的缓存行为,不影响后续 fetch 流程,是客户端侧的补充手段
- 低版本浏览器不支持时,仍需依赖服务端响应头 + 内容变更双保险
验证是否生效的简单方法
打开 Chrome DevTools → Network 标签页,刷新页面,找到 sw.js 请求,检查:
- Status 是否为 200(而非
304或200 (from disk cache)) - Response Headers 中是否有
Cache-Control: no-cache等预期值 - Response 内容是否与你刚部署的源码一致(尤其关注时间戳/版本注释)
只要 SW 脚本本身能被浏览器识别为“新”,后续的 waiting、activate、skipWaiting 等逻辑才能正常流转。否则所有提示、清理、更新操作都只是空中楼阁。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











