应结合 navigator.connection.effectivetype 和 downlink 判断网络质量,safari 需降级用加载时间探测或服务端注入网络提示,再动态插入 media="print" 后切换为 "all" 的 css 链接实现条件加载。

怎么判断当前网络是 4G 还是 WiFi?
浏览器没提供直接的 navigator.connection.type === 'wifi' 这种可靠 API。实际能用的只有 navigator.connection.effectiveType(如 '4g'、'3g'、'slow-2g'),但它不区分 WiFi 和有线,只反映“有效连接类型”——也就是说,WiFi 下如果信号差或后台限速,也可能返回 '3g'。
所以别硬判 WiFi,转而关注 effectiveType + downlink(估算带宽,单位 Mbps)组合更靠谱:
-
effectiveType是 Chrome/Edge/Firefox 支持的,Safari 完全不支持(navigator.connection为undefined) -
downlink值在 Safari 中存在但不可靠(常固定返回 10),Chrome 中相对可用 - 若两者都不可用,降级用
screen.width或 UA 字符串粗筛(不推荐,仅兜底)
如何动态加载不同尺寸的 CSS 文件?
不能靠 @import 或 link[rel=stylesheet] 的 media 属性做网络自适应——那些只响应视口、设备像素比,不感知网速。
必须用 JS 控制加载时机和目标 URL:
立即学习“前端免费学习笔记(深入)”;
- 尽早执行(比如放在
底部,避免阻塞渲染) - 优先加载最小版 CSS(如
base.min.css),再根据网络条件异步加载增强版(如enhanced.css) - 用
fetch()预检或直接创建link元素插入 DOM;不要用document.write(已废弃且会清空页面) - 注意:CSS 加载是异步的,但插入后会触发重排;建议加
media="print"插入,加载完再切回media="all",避免 FOUC
示例逻辑:
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = shouldLoadHeavyCSS() ? '/css/enhanced.css' : '/css/light.css';
link.media = 'print'; // 先隐藏
document.head.appendChild(link);
link.onload = () => link.media = 'all';为什么用 rel=preload 不适合这个场景?
<link rel="preload"> 是预加载资源,但不控制应用时机,也不支持条件逻辑。它会在 HTML 解析时立即发起请求,无法等 navigator.connection 判断完成后再决定加载哪个文件。
更关键的是:preload 后仍需手动 insertRule 或切换 link 的 disabled 状态,反而增加复杂度。不如直接用 JS 动态创建 link 干净。
- preload 适合已知必用、且路径确定的资源(如首屏字体、关键 JS)
- 这里路径和是否加载都取决于运行时网络状态,属于“条件加载”,不是“预加载”
- 滥用 preload 可能造成带宽浪费——比如在 2G 下 preload 了 500KB 的 CSS,用户根本不用
Safari 用户怎么办?
Safari 不支持 navigator.connection,所以所有基于它的判断都会 fallback。这不是 bug,是 Apple 明确拒绝实现该 API(隐私考虑)。
可行方案只有两个:
- 服务端通过 UA + IP 地址段(如运营商 ASN)粗略识别,然后注入初始网络标记到 HTML 中(如
window.__NET_HINT = '4g') - 客户端用加载时间试探:先发一个轻量探测请求(如
/ping?ts=123),记录responseEnd - fetchStart,再决定后续 CSS 版本 - 二者都不完美,但后者更可控;注意探测请求要小(
别指望一次判断覆盖所有情况。网络状况随时变,但 CSS 一般只加载一次。真正需要响应式样式的,应该靠 CSS 自身的媒体查询和现代特性检测(如 @supports),而不是反复换整张样式表。










