Service Worker 要真正离线运行 HTML,必须满足三条件:页面走 HTTPS(或 localhost)、sw.js 在根目录可访问、注册逻辑置于 window.addEventListener('load', ...) 中;否则静默失败。

Service Worker 要能真正离线运行 HTML,必须满足三个硬性条件:页面走 HTTPS(或 localhost)、sw.js 在根目录可访问、注册逻辑放在 window.addEventListener('load', ...) 里。缺一不可,否则静默失败。
注册必须等页面 load 完成且走安全上下文
浏览器只允许在安全上下文(HTTPS 或 localhost)中注册 Service Worker。http://127.0.0.1、http://test.local、file:// 全部不行,控制台不会报错,只是不执行。
- 注册代码不能写在
<script></script>标签里就直接调用,也不能塞进DOMContentLoaded回调 —— 此时navigator.serviceWorker可能尚未就绪 - 正确姿势是绑定到
window.addEventListener('load', ...),确保所有资源(含 CSS/JS)加载完毕 - 检查是否生效:打开 DevTools → Application → Service Workers,看到 “Active” 状态才算成功
- 如果显示 “Redundant”,说明新版本没激活,通常是因为
sw.js内容没变,浏览器跳过了更新
install 阶段必须预缓存完整 HTML 依赖链
cache.addAll() 不是“缓存页面”而是“缓存 URL 列表”,它不会自动解析 或 <script src></script>,你漏一个,离线时就 Failed to load resource: net::ERR_FAILED。
- 列表里至少包含:
'/'(即index.html),以及它直接引用的.css、.js、关键图片(如 logo) - 路径必须是绝对路径(以
/开头),比如'/app.js',不是'./app.js'或'assets/app.js' - 不要缓存带查询参数的 URL(如
'/data.json?v=1.2'),不同参数会被当不同键,浪费空间还容易击穿缓存 - 若某个资源 404 或跨域失败,
cache.addAll()整个失败 —— 可加.catch(() => {})防止阻塞 install,但得自己补日志排查
fetch 事件里必须单独处理 destination === 'document'
用户点链接、刷新页面、输入地址栏,触发的都是 destination === 'document' 请求。不专门拦截它,缓存再全也打不开 HTML —— 浏览器根本不会渲染。
- 错误写法:
event.respondWith(caches.match(event.request))—— 它会尝试匹配 POST 请求、带 cookie 的请求,导致登录态丢失或表单失效 - 正确写法:先判断
if (event.request.destination === 'document'),再用caches.match('/')或caches.match('/index.html')返回缓存 HTML - SPA(如 Vue Router history 模式)下,所有路由都应返回同一份
index.html,所以缓存时只存'/',fetch 时统一 fallback 到它 - 别信
navigationPreload:它默认开启,会绕过你的 fetch 逻辑直接发请求,必须显式禁用或手动处理
缓存更新和调试最容易忽略的细节
离线失败最常卡在“HTML 缓存了,但 JS 是新的”或“JS 缓存了,但 HTML 还是旧的”,本质是版本没对齐,而浏览器不会提醒你。
- HTML 文件若由服务端动态生成(如带 ETag),
fetch()可能返回 304,此时response.body为空,cache.put()会失败 —— 必须先检查response.status === 200 - 构建工具(Vite/Webpack)打包后,
index.html常被注入哈希化的 JS/CSS 路径,你缓存的 HTML 若没同步更新,离线时就会加载不到对应资源 - 修改
sw.js后,旧 SW 仍处于 “Waiting” 状态,除非用户关掉所有标签页再重开,或主动调用skipWaiting()+clients.claim() - DevTools 里看到 “Failed to load resource”,先看 Network 面板的 Initiator 列 —— 是 fetch() 发起的?还是 HTML 解析时自然加载的?二者处理逻辑完全不同
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











