如何利用 navigator.connection 的 saveData 降级低速网络资源,提升用户体验?
- 内容介绍
- 相关推荐
本文共计1095个文字,预计阅读时间需要5分钟。
不能仅靠`saveData`判断低速度网络——它仅表示用户主动开启了省流模式,与实际网速无关。真正要降低资源质量,得拆解使用:
为什么 saveData === true 必须无条件触发降级
saveData 是用户明确表达的偏好信号,不是估算值。Chrome、Edge、Opera 在开启“数据节省模式”时会主动拦截图片、延迟非关键脚本、压缩响应体,前端若不配合,会出现样式错乱、JS 执行失败、图片加载空白等问题。
- 只要
saveData === true,就该立即给document.documentElement加class="save-data",所有 CSS 降级规则(如.save-data img { display: none; })、JS 资源拦截逻辑(如跳过第三方统计、禁用动画库)都基于这个 class 控制 - 不要等
load或DOMContentLoaded:内联<script>放在<head>末尾,读取后立刻操作 DOM,否则首屏图片可能已发起请求 - React/Vue 中别在组件里判断:根组件或自定义 Hook 初始化时就读一次,避免子组件重复执行、触发多次重绘
effectiveType 和 downlink 怎么组合才不误判弱网
effectiveType 是浏览器根据 downlink 和 rtt 算出的粗分类,单独用它做开关极不可靠。比如 5G 下服务器在海外,rtt 高达 400ms,但 effectiveType 还是 "4g";而真实弱网下 downlink 可能从 1.2 → 0.7 → 1.5 频繁抖动。
- 优先看
downlink:低于 1.5 Mbps 且rtt > 300时,大概率出现卡顿,可触发图片/视频降级 -
effectiveType仅作辅助:比如effectiveType === "slow-2g"时,直接启用最简策略(320px WebP + 禁用懒加载),但不反过来推导——"4g"不代表网络一定好 - 必须加防抖:监听
navigator.connection.addEventListener("change", ...)时,用 800ms 防抖,避免downlink毛刺导致频繁切换清晰度
图片和视频资源怎么在请求发出前就降级
等 img 的 onerror 或视频播放失败再切,用户已经看到空白或卡顿了。正确做法是在 src 设置前就决策。
- 原始 HTML 别写死高清地址:
<img >,用 JS 根据网络状态动态赋值img.src - 降级函数示例:
function getLowQualitySrc(src) { const url = new URL(src); url.searchParams.set("q", "40"); url.searchParams.set("w", "320"); url.pathname = url.pathname.replace(/\.(jpg|jpeg|png)/, ".webp"); return url.toString(); } - 视频流更需谨慎:切换清晰度前检查
video.buffered.length > 0 && video.buffered.end(0) - video.currentTime ,否则强行切会中断播放
兼容性兜底和 Safari 的坑
navigator.connection 在 Safari 15.4+ 才支持 effectiveType 和 change 事件,桌面版 Safari 至今不支持 downlink 和 rtt。不处理就会在 iOS 上完全失效。
- 先做特性检测:
if (!("connection" in navigator)) { useFallbackStrategy(); },fallback 可以是navigator.onLine+ 历史资源加载耗时统计 - Safari 用户不能依赖
downlink:改用effectiveType(仅移动端可用)或主动测速(fetch 小文件 +performance.now()) - HTTP 环境下
navigator.connection大部分属性返回空值或默认值,必须确保站点跑在 HTTPS 上
真正难的不是读取那几个属性,而是把 saveData 的确定性、downlink 的抖动性、浏览器兼容性的碎片化,揉进同一套降级逻辑里——稍有不慎,用户就在“省流模式”下看到高清图加载失败,或在 4G 下被强制切到 320px 版本。动手前先想清楚:哪条路径是强约束,哪条只是参考,哪条根本不存在。
本文共计1095个文字,预计阅读时间需要5分钟。
不能仅靠`saveData`判断低速度网络——它仅表示用户主动开启了省流模式,与实际网速无关。真正要降低资源质量,得拆解使用:
为什么 saveData === true 必须无条件触发降级
saveData 是用户明确表达的偏好信号,不是估算值。Chrome、Edge、Opera 在开启“数据节省模式”时会主动拦截图片、延迟非关键脚本、压缩响应体,前端若不配合,会出现样式错乱、JS 执行失败、图片加载空白等问题。
- 只要
saveData === true,就该立即给document.documentElement加class="save-data",所有 CSS 降级规则(如.save-data img { display: none; })、JS 资源拦截逻辑(如跳过第三方统计、禁用动画库)都基于这个 class 控制 - 不要等
load或DOMContentLoaded:内联<script>放在<head>末尾,读取后立刻操作 DOM,否则首屏图片可能已发起请求 - React/Vue 中别在组件里判断:根组件或自定义 Hook 初始化时就读一次,避免子组件重复执行、触发多次重绘
effectiveType 和 downlink 怎么组合才不误判弱网
effectiveType 是浏览器根据 downlink 和 rtt 算出的粗分类,单独用它做开关极不可靠。比如 5G 下服务器在海外,rtt 高达 400ms,但 effectiveType 还是 "4g";而真实弱网下 downlink 可能从 1.2 → 0.7 → 1.5 频繁抖动。
- 优先看
downlink:低于 1.5 Mbps 且rtt > 300时,大概率出现卡顿,可触发图片/视频降级 -
effectiveType仅作辅助:比如effectiveType === "slow-2g"时,直接启用最简策略(320px WebP + 禁用懒加载),但不反过来推导——"4g"不代表网络一定好 - 必须加防抖:监听
navigator.connection.addEventListener("change", ...)时,用 800ms 防抖,避免downlink毛刺导致频繁切换清晰度
图片和视频资源怎么在请求发出前就降级
等 img 的 onerror 或视频播放失败再切,用户已经看到空白或卡顿了。正确做法是在 src 设置前就决策。
- 原始 HTML 别写死高清地址:
<img >,用 JS 根据网络状态动态赋值img.src - 降级函数示例:
function getLowQualitySrc(src) { const url = new URL(src); url.searchParams.set("q", "40"); url.searchParams.set("w", "320"); url.pathname = url.pathname.replace(/\.(jpg|jpeg|png)/, ".webp"); return url.toString(); } - 视频流更需谨慎:切换清晰度前检查
video.buffered.length > 0 && video.buffered.end(0) - video.currentTime ,否则强行切会中断播放
兼容性兜底和 Safari 的坑
navigator.connection 在 Safari 15.4+ 才支持 effectiveType 和 change 事件,桌面版 Safari 至今不支持 downlink 和 rtt。不处理就会在 iOS 上完全失效。
- 先做特性检测:
if (!("connection" in navigator)) { useFallbackStrategy(); },fallback 可以是navigator.onLine+ 历史资源加载耗时统计 - Safari 用户不能依赖
downlink:改用effectiveType(仅移动端可用)或主动测速(fetch 小文件 +performance.now()) - HTTP 环境下
navigator.connection大部分属性返回空值或默认值,必须确保站点跑在 HTTPS 上
真正难的不是读取那几个属性,而是把 saveData 的确定性、downlink 的抖动性、浏览器兼容性的碎片化,揉进同一套降级逻辑里——稍有不慎,用户就在“省流模式”下看到高清图加载失败,或在 4G 下被强制切到 320px 版本。动手前先想清楚:哪条路径是强约束,哪条只是参考,哪条根本不存在。

