静态html离线可用需service worker按request.destination分流处理:document必须缓存或fallback到/offline.html,script/style需绝对路径预缓存,font/image用try/catch兜底,json放行;install阶段cache.addall须用绝对路径全量缓存依赖项且校验响应头;html版本更新靠fetch拦截+响应头比对实现后台校验;offline.html须显式加入缓存且无动态内容;缓存命名须带版本哈希并在activate阶段清理旧缓存。

静态 HTML 页面要真正扛住网络波动,不能只靠“缓存住”,而得让每个资源加载环节都有 fallback、有探测、有兜底——漏掉 script 或 font,离线时照样白屏或报错。
Service Worker 中 fetch 事件必须按 destination 分流处理
浏览器对不同资源的请求会带上 request.destination,比如 HTML 页面是 'document',JS 是 'script',字体是 'font'。不区分就统一走 caches.match(event.request),后果很直接:POST 请求被当成静态资源返回缓存,表单提交无声失败;字体请求卡住,整页渲染阻塞。
-
event.request.destination === 'document':必须命中缓存,否则用户刷新就白屏;建议 fallback 到预置的'/offline.html'响应字符串 -
=== 'script'或=== 'style':可直接caches.match(),但需确保 install 阶段已完整缓存其绝对路径(如'/app.js',不是'app.js') -
=== 'font'或=== 'image':建议用try/catch包裹caches.match(),失败则放行到网络,避免单个图标缺失拖垮整页 -
=== 'json'或空字符串(如 API 调用):绝不能塞进主缓存,应放行或走stale-while-revalidate策略
install 阶段缓存必须覆盖完整加载链,且路径全为绝对根路径
cache.addAll() 是原子操作:列表里任一资源返回 404、CORS 拒绝、MIME 类型不匹配(比如服务器把 .woff2 当成 text/plain 返回),整个缓存就中断,一个文件都不会写入。
- 必须显式列出所有依赖项:
'/index.html'、'/css/main.css'、'/js/app.js'、'/fonts/icon.woff2'—— 相对路径、带查询参数的路径(如'/app.js?v=1.2')全部无效 - HTML 文件本身必须进缓存;很多项目只缓了 JS/CSS,却忘了
/index.html,结果断网后连主文档都拿不到 - 检查服务器响应头:
index.html若含Cache-Control: no-store,cache.addAll()会直接拒绝缓存它
HTML 版本校验与动态更新不能依赖 manifest,要用响应头 + fetch 拦截
AppCache 已废弃,Chrome 95+ 彻底移除 window.applicationCache。现在想让离线 HTML 在上线后及时更新,得靠 Service Worker 主动探测。
- 在
fetch事件中拦截 HTML 请求:if (event.request.url.endsWith('.html')) - 用
fetch(event.request)发起网络请求,读取响应头res.headers.get('X-HTML-Version') - 若该值与当前缓存版本(如全局常量
CACHED_HTML_VERSION)不一致,触发离线包整体更新逻辑(如下载新资源清单并重装 SW) - 注意:这个探测不能阻塞页面加载,建议用
event.respondWith()先返回缓存,再后台 fetch 校验
离线降级页面(offline.html)本身必须被缓存,且不能含动态脚本
很多人设了 FALLBACK: / /offline.html,却没把 /offline.html 加进 install 缓存列表——结果断网时连 fallback 页面都加载不了,最终还是 404 或白屏。
-
/offline.html必须出现在cache.addAll([...])的数组里,路径为绝对根路径 - 该页面内不能有
document.write、不能依赖服务端注入的变量(如<meta name="version" content="{{build_time}}">),这些内容离线时无法更新 - 避免内联脚本执行关键 DOM 操作;所有逻辑应打包进已缓存的 JS 文件中,否则离线时脚本丢失,页面功能残缺
最易被忽略的一点:缓存命名不带版本哈希,activate 阶段又没调用 caches.delete() 清理旧缓存,会导致浏览器永远用着过期的 app.js,而你根本不知道它没更新。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











