navigator.connection.saveData 是唯一可靠省流检测方式,但需三重防护判断且必须在 HTML 解析阶段内联执行,配合资源拦截与手动开关机制。

navigator.connection.saveData 是目前唯一可靠、语义明确的省流检测方式,但必须加防护性判断——它在 Safari 和多数桌面浏览器中直接不可用,且部分安卓 WebView 不同步系统设置。
为什么不能只用 navigator.connection 存在性判断
很多浏览器(如 Safari、旧版 Chrome、某些 WebView)会返回一个“空壳”对象:navigator.connection 存在,但所有属性都是 undefined 或默认值(比如 downlink: 0、type: "")。直接读取 saveData 会报 Cannot read property 'saveData' of null 或返回 undefined。
必须按顺序检查:
"connection" in navigatornavigator.connection !== null"saveData" in navigator.connection
三者全为真,才可安全读取 navigator.connection.saveData。漏掉任一环,线上就可能触发 JS 错误或误判。
立即学习“前端免费学习笔记(深入)”;
检测时机必须早于 DOM 渲染
等 DOMContentLoaded 或 React 的 useEffect 执行时,图片、字体、第三方脚本往往已发起请求——省流已经失效。
正确做法是:在 <head> 中内联一段 <script>,紧贴 <meta charset> 后,不带 async 或 defer:
<script>
if ("connection" in navigator && navigator.connection !== null && "saveData" in navigator.connection) {
if (navigator.connection.saveData) {
document.documentElement.classList.add("save-data");
}
}
</script>
这样可在 HTML 解析阶段就打上 save-data class,让 CSS 规则立即生效,避免重排重绘。
仅靠 CSS 隐藏不够,必须拦截资源请求
html.save-data img { display: none; } 只是视觉隐藏,src 仍会加载——流量照跑。
真正省流要主动干预资源加载逻辑:
- 懒加载图片:把
loading="lazy"改为eager,并切换到低分辨率占位图(img.src = img.dataset.lowres) - 跳过 WebP/AVIF:强制用
jpeg或svg,避免格式协商开销 - 禁用非关键脚本:统计、推荐、埋点等,在
saveData为true时不调用loadAnalytics() - API 路由降级:fetch 地址从
/api/full切到/api/light
这些动作必须在 JS 中显式判断 navigator.connection.saveData,不能依赖 CSS class 反向推导。
别指望 change 事件或轮询
navigator.connection.saveData 是只读静态值,**不会触发 change 事件**。iOS 的 webkitnetworkinfochanged 兼容性极差,几乎无法落地。
真实场景中,用户开启/关闭省流模式后会刷新页面——所以只需在首屏加载时检测一次即可。强行轮询或监听事件,既无效果又增加内存负担。
最易被忽略的一点:自动切换必须配手动开关。用户可能在弱网下也想看高清图,或在 WiFi 下开了省流却忘了关。CSS class 和 JS 行为都要支持运行时动态增删,且状态需持久化(例如 localStorage),否则刷新即失效。



















