Service Worker已激活且在作用域内,但未触发fetch事件的条件咨询
这种情况我之前踩过好几个坑,明明Service Worker显示激活了、请求也在它的作用域范围内,可fetch事件就是纹丝不动。大概率是下面这些容易被忽略的条件没满足,你可以逐一排查:
请求类型不在拦截范围内:Service Worker并不是啥请求都管的,像
chrome-extension://这类浏览器扩展请求、blob:///data://这类本地资源请求,默认都不会触发fetch事件。另外,跨域请求如果用了mode: 'no-cors',也可能绕开Service Worker的拦截。还有要注意:页面的初始HTML请求,要是在Service Worker激活之前就发起了,那这次请求也不会被拦截——得刷新页面(或者下次打开页面)才会走Service Worker的逻辑。HTTPS环境限制(本地开发除外):Service Worker只能在HTTPS环境下正常工作,唯一例外是
localhost或127.0.0.1这类本地开发地址。如果你的站点是HTTP协议(非本地),哪怕Service Worker激活了,fetch事件也绝对不会触发。Service Worker脚本的监听器有问题:别觉得这是废话,真的很容易写错!得确保你的Service Worker脚本里正确注册了fetch事件监听器,比如:
self.addEventListener('fetch', (event) => { // 至少要有基础的处理逻辑,哪怕只是打个日志测试 console.log('Fetch事件触发:', event.request.url); // 别忘了调用respondWith,不然请求会默认走网络 event.respondWith(fetch(event.request)); });如果脚本里有语法错误,或者监听器根本没写对位置,那自然不会触发fetch事件。
浏览器强缓存跳过了网络请求:如果请求的资源已经被浏览器强缓存(比如响应头带了
Cache-Control: max-age=xxx且还在有效期内),浏览器会直接从本地缓存取资源,根本不会发起网络请求——那Service Worker的fetch事件当然不会触发。你可以在开发者工具的Network面板勾选「Disable cache」,再测试一次看看是不是这个问题。误判了Service Worker的激活状态:有时候看起来Service Worker是「Activated」状态,但其实旧的脚本还在运行,新脚本卡在「Waiting」状态(比如还有未关闭的标签页在使用旧脚本)。你可以打开Chrome DevTools的「Application -> Service Workers」面板看看,如果有两个脚本共存,要么关闭所有相关标签页再重新打开,要么点击「Skip waiting」强制激活新脚本。
隐私模式的限制:部分浏览器在隐私/隐身窗口下会限制Service Worker的功能,甚至直接禁用它,导致fetch事件无法触发。可以切换到正常窗口再测试一遍。
内容的提问来源于stack exchange,提问作者garviand

