用 navigator.online 判断浏览器离线最直接但不可靠,需结合定时 fetch 探测与 online/offline 事件监听,并通过 service worker 缓存关键资源、fallback 离线页,移动端需适配 webview 差异。

怎么判断浏览器是否离线
用 navigator.onLine 最直接,但它只反映网络接口状态,不是真实连通性判断。比如 WiFi 已连接但路由器断网,navigator.onLine 仍返回 true。
实际要用「探测 + 监听」组合:
- 页面加载后立即发一个轻量
fetch('/offline-test.txt?'+Date.now()),超时或 404/500 就当离线 - 同时监听
online和offline事件,但别全信——它们可能延迟数秒甚至不触发(尤其安卓 WebView) - 避免轮询:每 15 秒以上才重试探测,否则耗电、触发 CORS 预检、被服务端限流
离线时怎么不让页面白屏或报错
核心是拦截关键资源请求并 fallback。不能等 fetch 报错才处理,得提前预判。
- 所有动态
fetch必须带catch,且 catch 里检查navigator.onLine再决定展示缓存内容还是离线提示 - HTML 中的
<script src="..."></script>和<link rel="stylesheet" href="...">无法 JS 拦截,得靠 Service Worker 注册后主动缓存关键资源 - Service Worker 的
install阶段缓存index.html、主 JS/CSS、离线页offline.html;fetch事件里匹配不到资源时return caches.match('offline.html')
Service Worker 缓存策略怎么写才不翻车
缓存路径写错、版本没更新、跳过等待逻辑漏掉,都会导致离线失效或旧资源卡死。
立即学习“前端免费学习笔记(深入)”;
-
cacheName必须带版本号,如'v2-static-cache',每次变更缓存策略就改名字,避免旧 SW 读错 cache - 注册 SW 后立即调用
registration.waiting.postMessage('skipWaiting'),否则新 SW 会卡在 waiting 状态,离线时仍用旧逻辑 - 不要缓存带查询参数的 URL(如
/api/user?id=123),它们无法命中;API 类请求应单独用 IndexedDB 存结构化数据 - 缓存 HTML 时用
cache.put('/', response.clone()),别漏掉clone(),否则响应体被读一次就空了,后续 fetch 拿不到内容
移动端 WebView 里离线检测为什么经常失灵
Android 的 WebView 和 iOS 的 WKWebView 对 navigator.onLine 实现不一致,且部分厂商系统会禁用网络事件。
- 安卓 7.0+ 的 WebView 默认关闭
online/offline事件,需在初始化时加webView.getSettings().setJavaScriptEnabled(true)并确保WebSettings.setAppCacheEnabled(true) - iOS WKWebView 不触发
offline事件是已知 bug,必须靠定时 fetch 探测,不能依赖事件 - 微信内置浏览器(X5 内核)会伪造
navigator.onLine === true即使断网,唯一可靠方式是每 8–10 秒发一次HEAD请求到自己域名下的小文件(如/healthz)
离线逻辑越早介入越好——从 HTML 加载完成就开始探测,而不是等 Vue/React 初始化完再启动。很多“离线失败”其实是因为 JS 还没执行,页面已经因资源加载失败白屏了。











