只要在Service Worker中预缓存offline.html等资源并拦截导航请求,在网络失败时返回该页面,即可实现无网自定义提示页;需确保离线页自包含、缓存版本及时更新、fetch兜底逻辑完整。

只要在 Service Worker 中拦截所有网络请求,并对失败请求返回一个预缓存的离线 HTML 页面,就能实现无网时展示自定义提示页。关键在于缓存策略、请求拦截逻辑和离线页的可靠注入。
预缓存离线页面文件
在 Service Worker 安装阶段,把离线页(如 offline.html)和必要资源(CSS、图标等)一并加入缓存。推荐使用 workbox-precaching 或手动调用 caches.open().add():
- 离线页需是完整 HTML(含 <html><body>),不能是纯文本或 JSON
- 确保路径准确,比如
new Request('/offline.html')要与实际部署路径一致 - 若用 Workbox,可在
precacheAndRoute([ { url: '/offline.html', revision: '1' } ])中声明
拦截所有导航请求并兜底返回离线页
监听 fetch 事件,专门捕获 request.mode === 'navigate' 的页面跳转请求。这类请求失败时(如网络断开、DNS 失败、504 等),直接从缓存读取离线页:
- 用
event.respondWith()包裹响应逻辑,避免默认网络行为 - 先尝试
fetch(event.request),用 catch() 捕获网络异常(注意:不是所有失败都会进 catch,需结合response.ok判断) - 兜底时用
caches.match('/offline.html')获取缓存内容,确保返回的是 Response 对象(不是字符串)
确保离线页本身不触发额外网络请求
离线页一旦加载,必须完全自包含,否则会因二次请求失败导致白屏或样式错乱:
- 内联关键 CSS(避免
<link rel="stylesheet">)、用 data URL 加载小图标 - 移除所有外部 JS(如统计脚本、CDN 字体)、禁用动态 fetch 或图片懒加载
- 可加简单脚本检测联网状态,例如
navigator.onLine+ 定时fetch('/health')尝试恢复,但非必需
更新与调试要点
Service Worker 更新机制容易导致离线页不生效,需主动管理:
- 每次修改离线页后,务必更新其缓存版本(如改文件名、加时间戳 query、或更新 Workbox 的 revision)
- 开发时在 Chrome DevTools 的 Application → Service Workers 中勾选 “Update on reload”,并点击 “Unregister” 清旧版
- 用
chrome://serviceworker-internals/查看当前激活的 SW 和缓存内容,确认 offline.html 已缓存

















