最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何用Service Worker实现即使在无网环境下也能显示的离线提示页
时间:2026-07-21 11:34:49 编辑:袖梨 来源:一聚教程网
Service Worker离线提示页必须预缓存静态/offline.html路径,仅响应导航请求(destination==='document'或mode==='navigate'),用503状态码构造Response返回,且该HTML须零外部依赖。
能实现,但必须提前缓存提示页本身,且不能依赖运行时 fetch 拦截失败后跳转——Service Worker 的离线响应必须来自 cache storage 或 self.skipWaiting() 之后的已激活状态。
注册时确保 Service Worker 已安装并激活
很多开发者以为注册完就能立刻拦截请求,其实注册只是触发 install 阶段,而 fetch 事件只在 activate 后生效。如果用户首次访问就断网,install 阶段失败(比如提示页资源没加载完),整个离线逻辑就崩了。
-
navigator.serviceWorker.register()后要监听waiting和active状态,必要时调用sw.waiting.postMessage('skipWaiting') - 在
install事件里用event.waitUntil(caches.open('offline-v1').then(cache => cache.addAll(['/offline.html'])))预缓存提示页,路径必须和后续 fetch 中匹配 - 不要在
install里缓存动态路由(如/user/123),/offline.html必须是静态可预知路径
fetch 事件中区分导航请求与资源请求
浏览器对页面导航(request.destination === 'document')和脚本/CSS/图片等资源的处理逻辑不同。离线提示页只应响应导航请求,否则可能把 JS 文件也替换成 HTML,导致白屏或报错。
- 用
if (request.destination === 'document')过滤,避免误劫持.js、.css请求 - 检查
event.request.mode === 'navigate'更稳妥,因为部分浏览器对直接地址栏输入也会发destination: 'document' - 不要用
fetch(request).catch(...)做兜底——离线时 fetch 会直接 reject,但你得在 reject 前就决定返回缓存还是 fallback
返回离线页时注意响应头与状态码
直接 Response.redirect('/offline.html') 在离线时会失败(重定向需要网络),必须用 new Response(body, { status: 503, headers: { 'Content-Type': 'text/html' } }) 构造完整响应。
- 从 cache 中读取
/offline.html后,要用response.text()解析 body,再 new Response(body, options),不能直接 return response —— 因为 cache.put 保存的是 Response 对象,但 cache.match 返回的 response.body 已被读取过一次,需重新构造 - 状态码建议用
503(Service Unavailable)而非200,便于调试时在 DevTools Network 面板一眼识别是离线 fallback - 确保
/offline.html自身不引用任何外部资源(如 CDN 字体、第三方 JS),否则它自己也会加载失败
最常被忽略的一点:缓存策略不是“有就行”,而是“install 时必须成功写入 + activate 后能稳定读取”。哪怕只差一个斜杠(比如缓存了 offline.html 却在 fetch 里匹配 /offline.html),或者 HTML 里写了 <script src="/js/app.js"></script> 但没缓存该 JS,离线页都会半残。真实环境里,多一个相对路径、少一个 event.waitUntil 包裹,就足以让整个离线流程静默失效。
相关文章
- 大店小二门客如何获取 07-31
- csgo饰品交易哪个平台适合 07-31
- LSTM-Kirigaya/slidev-mcp skill 本地安装使用教程(新手) 07-31
- 怎么玩最强斗王手游月卡 07-31
- 魔兽世界怀旧服野外PVP需要何种装备 07-31
- 仁王3三个隐藏BOSS何处 07-31