rel="preload"配as="style"必须配合onload="this.onload=null;this.rel='stylesheet'"才能生效,否则仅下载不解析不挂载;this.onload=null须前置防重复执行,且href路径须与后续引用完全一致,否则触发二次请求。

as="style" 必须配 onload 才能生效
只写 <link rel="preload" href="main.css" as="style"> 是无效的——它只会下载 CSS 文件,但不会解析、不会挂载到 CSSOM,页面依然无样式。浏览器把 preload 当作“提前拉取”,不是“提前应用”。
必须加 onload="this.onload=null;this.rel='stylesheet'",且 this.onload=null 要放在最前,否则缓存复用或脚本重入时可能触发多次 rel 切换,导致样式重复计算或 DOM 重排。
- 漏掉
this.onload=null:Chrome 和 Safari 在资源从内存缓存加载时仍会触发 onload,造成二次rel设置,部分浏览器会报错Failed to execute 'insertRule' on 'CSSStyleSheet' - 把
this.rel='stylesheet'写在前面、this.onload=null写在后面:存在极小概率(如 onload 异步回调被中断)导致下一次同 URL 的 preload 再次执行 - 用
onreadystatechange替代onload:现代浏览器不保证触发,且无法区分成功/失败,已弃用
路径必须完全一致,否则触发二次请求
如果同时存在 <link rel="preload" href="a.css" as="style"> 和 <link rel="stylesheet" href="./a.css">,哪怕只是斜杠差异或查询参数不同(如 a.css?v=1 vs a.css),浏览器就会当作两个资源,发起两次请求。
这种重复不仅浪费带宽,还会挤占首屏关键资源的 TCP 连接和 HTTP/2 流,尤其在弱网下明显拖慢交互就绪时间。
立即学习“前端免费学习笔记(深入)”;
- 检查点包括:大小写(
Style.css≠style.css)、尾部斜杠(/css/vs/css)、查询参数(?t=123)、hash 后缀(构建产物如main.abc123.css) - 服务端渲染(SSR)项目中,若构建时生成了 hash,需用构建插件自动同步 preload 的 href,不能手写
- 本地开发用 Live Server 时,注意它默认不处理 query 参数缓存策略,容易掩盖路径不一致问题
preload 必须写在 HTML parser 阶段,动态插入无效
rel="preload" 只在 HTML 解析过程中被识别。JS 动态创建 link 标签并 append 到 head,无论多早执行(哪怕在 <script> 中立即运行),都不会触发预加载。
正确位置是:<meta charset> 之后、<title> 之前;错误位置包括:任何 <body> 内、<link rel="stylesheet"> 下方、<script> 块之后。
- SSR 模板里写错顺序(比如把 preload 放在 title 后面),DevTools 的 Network 面板里 Priority 显示为
Low,Initiator 是(Other),说明已降级为普通 fetch - 使用 Webpack/Vite 等构建工具时,确保插件注入的 preload 标签严格落在 head 开头区域,而非拼接到已有 link 后面
- 测试是否生效:打开 DevTools → Network → 找对应 CSS 请求 → 看 Priority 是否为
Highest或High,且 Initiator 是Parser
非关键 CSS 里藏着的字体和图片会反向拖慢首屏
你把 chart.css 设成 preload + onload,以为首屏就安全了,但如果它里面写了 @font-face src: url('heavy.woff2') 或 background-image: url('/hero-banner.jpg'),这些子资源会在 CSS 挂载后才开始拉取——而它们的下载会抢占首屏 JS/CSS 的带宽和连接数。
也就是说,异步加载只是卸下了“CSS 主文件”的阻塞,没解除它所依赖的“子资源”的加载时机控制。
- FOUC(闪屏)可能不出现,但 LCP(最大内容绘制)和 INP(交互延迟)仍会被拖累
- CDN 图片若未开启 Brotli 压缩、或 woff2 字体未做 subsetting,单个资源就可能 >1MB,比整个首屏 HTML 还大
- 解决方案不是放弃 preload,而是对非关键 CSS 做“依赖审计”:用
curl -I或 DevTools 的 Coverage 工具检查它实际拉了哪些额外资源



















