html离线白屏主因是缓存未覆盖完整依赖链,install阶段须用cache.addall()原子缓存绝对路径的html及其所有引用资源(如/main.css、/app.js),fetch事件按destination精准分流,activate阶段必须清理旧缓存并版本化命名。

install阶段必须缓存完整HTML依赖链,不能只写/index.html
离线时白屏,往往不是因为HTML没缓存,而是它引用的main.css、app.js、logo.png等资源根本没进缓存。浏览器加载/index.html后会按顺序发起这些请求,任一失败就触发net::ERR_FAILED。
cache.addAll()是原子操作:列表里任意一项返回404、CORS拒绝、或MIME类型不匹配(比如字体被当成text/plain),整个缓存就中断,一个文件都不会写入。
- 所有路径必须是绝对根路径:
'/index.html'✅,'index.html'❌,'./main.css'❌ - 带查询参数的URL会被视为不同资源:
'/static/app.js?v=1.2'❌,应统一用无参路径+构建时哈希命名 - 检查服务器实际响应头:如果
/index.html返回Cache-Control: no-store,cache.addAll()会直接拒绝缓存它
fetch事件里必须按request.destination分流处理
把所有请求都无差别丢给caches.match(event.request),等于让Service Worker把POST /login、fetch('/api/user')也当静态资源查缓存——结果就是表单提交无声无息、cookie丢失、用户以为点了但什么都没发生。
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
-
event.request.destination === 'document':页面首次加载或刷新,必须命中缓存,否则白屏;建议fallback到预存的'/offline.html'字符串响应 -
=== 'script'或=== 'style':可直接caches.match(),静态资源缓存优先没问题 -
=== 'font'或=== 'image':建议加try/catch,失败就跳过缓存,避免单个图标缺失阻断整页渲染 -
=== 'json'或空字符串(如fetch('/api/user')):这类API请求应放行到网络,或走stale-while-revalidate,别塞进离线主缓存
缓存命名与activate阶段清理旧缓存不可省略
缓存名写死成'v1'看似简单,但更新资源后,新SW安装时旧缓存不会自动删,浏览器可能继续用过期的app.js,而你根本不知道。
- 缓存名建议带构建时注入的哈希或时间戳:
static-v${VERSION},其中VERSION来自Webpack的DefinePlugin或Vite的define -
activate阶段必须调用caches.delete()清理非当前版本的缓存,否则旧缓存永远占位 - 不要依赖
self.skipWaiting()强制激活——它会让新SW立即接管已有页面,可能造成JS版本错配
HTML文档结构本身要支持离线托管,不能依赖服务端动态生成
如果/index.html是服务端模板渲染的(比如Express的res.render('index')),每次返回内容可能不同,且常带Cache-Control: no-cache或no-store,cache.addAll()会直接失败。
- 离线可用的HTML必须是纯静态文件,由构建工具输出(如Vite build、Webpack output),确保内容稳定、可预测
- 关键标签如
<link rel="stylesheet">、<script src></script>、<img src>里的路径必须是绝对根路径,且与cache.addAll()中列出的完全一致 - 避免在HTML中内联大量JS/CSS逻辑——它们无法被单独缓存更新,容易导致版本漂移
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










