Service Worker调试失败主因是上下文错误、请求归类不清或生命周期未触发;需确认HTTPS/localhost环境、DOMContentLoaded前注册、sw.js返回2xx响应;fetch事件仅拦截同源主动请求,Network中属Other分类,更新需skipWaiting+clients.claim。

Service Worker 调试失败,八成不是代码写错了,而是没进对上下文、没看清请求归类、或根本没触发 install/activate 生命周期。
DevTools 里找不到 Service Worker 面板
Application → Service Workers 面板不显示,常见原因有三个:
- 页面不是 HTTPS 或 localhost ——
navigator.serviceWorker在file://或 HTTP 非本地环境直接不可用,控制台会报Failed to register a ServiceWorker: The URL protocol of the current page is not supported - 注册脚本执行太晚,比如放在
window.onload之后,或被包裹在某个异步回调里;应确保navigator.serviceWorker.register('/sw.js')在DOMContentLoaded前调用 -
sw.js返回了非 2xx 状态码,或响应头含Cache-Control: no-cache(Chrome 会拒绝解析),可用 Network 面板过滤sw.js查看响应头和状态
fetch 事件断点不触发 / 日志没输出
Service Worker 的 fetch 事件只拦截同源、由页面主动发起的请求(fetch()、XMLHttpRequest、<img>、<script> 等),以下情况不会触发:
- iframe 加载的跨域页面
- 未带 CORS 头的跨域图片/字体(浏览器静默失败,不走 SW)
-
navigator.sendBeacon()发出的请求 - SW 自身安装时加载的脚本(如
self.importScripts())
验证是否进入 fetch:在 sw.js 里加 console.log('fetch:', event.request.url),然后打开 DevTools → Console → 左上角环境切换按钮 → 选 service_worker (sw.js)。若没这个选项,说明 SW 还没激活(需至少一次页面加载 + 注册成功)。
立即学习“前端免费学习笔记(深入)”;
缓存生效但接口数据不对 / CORS 报错
用 caches.match() 返回缓存响应时,容易忽略两点:
- 缓存的
Response对象自带 headers(包括Content-Type),但若原始响应含Access-Control-Allow-Origin,而你用new Response(body)重构造,这些 headers 就丢了 → 导致 CORS 失败。正确做法是:return new Response(cacheRes.body, cacheRes) - 对流式响应(如
text/event-stream)直接调response.json()会报错,因为流只能读一次;需先response.clone().json(),再把原response返回 - 修改请求 URL 后没透传 method / body / headers,例如
fetch(new Request(newUrl))会丢掉原请求体,应显式传入:new Request(newUrl, { method: req.method, headers: req.headers, body: req.body })
Network 面板看不到 SW 拦截的请求
Service Worker 返回的响应在 Network 面板中归类为 Other 类型,不是 XHR 或 Fetch —— 所以默认过滤器下会消失。解决方法:
- 在 Network 面板顶部过滤栏输入
Other,或清空过滤器后手动找 - 右键某条请求 → “Replay XHR” 不起作用(它不走 SW),要用 “Copy as fetch” 然后在 Console 中粘贴执行,才能复现 SW 拦截逻辑
- 想确认某次请求是否被 SW 拦截,可在
fetch事件中加event.respondWith(Promise.resolve(new Response('sw-hit'))),再看 Network 是否返回该字符串
最易被忽略的是:即使你更新了 sw.js 文件,旧版仍控制着已打开的页面,除非主动调用 self.skipWaiting() 并在 activate 中执行 clients.claim() —— 否则你在 DevTools 里看到的永远是老逻辑。



















