Service Worker注册后fetch事件未触发,主因是HTTPS缺失(localhost除外)、SW路径错误致注册失败,或作用域限制导致请求不匹配;需检查控制台报错及Application面板状态,并确保offline.html在install阶段缓存且fetch中用相同缓存名匹配。

Service Worker 注册后没触发 fetch 事件?
常见原因是页面没走 HTTPS(本地 localhost 除外),或 SW 文件路径不正确导致注册失败。用 navigator.serviceWorker.register() 后务必检查控制台是否有 Failed to register a ServiceWorker 错误,以及 Application > Service Workers 面板里是否显示 “Waiting” 或 “Active”。SW 只对同源下注册路径的子路径生效——比如注册在 /sw.js,那它只能拦截 /a/、/api/ 等路径,但无法拦截 /admin/sw.js 这种上级路径。
离线时 fallback 到指定 HTML 页面的关键逻辑
核心是监听 fetch 事件,在 event.respondWith() 中判断网络状态并返回响应。不能只靠 navigator.onLine,它不可靠;应以 fetch 失败为依据。常见写法是先尝试网络请求,catch 到错误后再 match fallback 页面:
self.addEventListener('fetch', event => {
if (event.request.destination === 'document') {
event.respondWith(
fetch(event.request).catch(() => caches.match('/offline.html'))
);
}
});
注意点:
-
/offline.html必须提前缓存在 install 阶段,否则caches.match()返回undefined - 如果 fallback 页面本身引用了外部 CSS/JS,这些资源也得进缓存,否则离线打开仍会白屏或样式错乱
- 避免对所有请求都 fallback——比如 API 请求应直接 reject,而不是返回 HTML,否则前端 JSON 解析会报错
caches.open() 和 caches.match() 的缓存名要一致
install 阶段用 caches.open('v1') 缓存 /offline.html,fetch 阶段就得用同样的名字去 match,否则查不到。更稳妥的做法是把缓存名抽成常量:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
立即学习“前端免费学习笔记(深入)”;
const CACHE_NAME = 'offline-fallback-v1';
另外,缓存策略建议用 CacheFirst 对静态资源,但对 /offline.html 本身,只要确保 install 时写入一次即可,无需每次更新。
调试离线 fallback 时容易忽略的细节
Chrome DevTools 的 “Offline” 模式只是禁用网络,不会触发 SW 的 fetch error 流程(因为 fetch 仍能发出去,只是被拦掉),所以测试必须真断网或用 chrome://serviceworker-internals/ 手动 stop + skip waiting 再刷新。还有两个坑:
- 修改 SW 文件后,浏览器可能还在用旧版本——需手动
Update on reload或关闭所有标签页再开 -
/offline.html里的相对路径(如./style.css)在离线时会 404,必须用绝对路径或提前缓存所有依赖 - 如果页面是 SPA,且路由由前端控制(如 React Router),
/offline.html需包含完整骨架和 JS,否则用户刷新后看到的是空白,而不是“已离线”提示

















