rel="preload" 不自动生效,因其语义仅为提前获取资源;必须搭配as="style"和onload中将rel改为"stylesheet"才能应用样式,否则仅缓存不解析。

预加载关键 CSS 时,rel="preload" 本身不触发样式应用,必须搭配 as="style" 和后续的 onload 注入逻辑,否则浏览器只会下载但不生效。
为什么 rel="preload" 加载的 CSS 不会自动生效
浏览器对 rel="preload" 的语义理解是“提前获取资源”,不是“立即使用”。即使你写了 <link rel="preload" href="main.css" as="style">,它只进缓存,不解析、不渲染。这是设计使然,不是 bug。
-
as="style"必须显式声明,否则浏览器可能以as="fetch"处理,导致 CSP 拦截或优先级降级 - 缺少
onload或 JS 注入步骤 → 样式永远不会挂载到 DOM - 若同时存在普通
<link rel="stylesheet">引用同一文件,可能引发重复下载(尤其在 HTTP/1.1 下)
正确注入预加载 CSS 的最小可行写法
在 <head> 中放预加载标签,再紧跟一段内联脚本完成注入。注意顺序和时机:
<link rel="preload" href="/css/critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'"> <noscript><link rel="stylesheet" href="/css/critical.css"></noscript>
-
onload="this.onload=null;this.rel='stylesheet'"是关键:等预加载完成,立刻把link转为样式表 -
this.onload=null防止重复执行(某些浏览器会触发多次) -
<noscript>保障无 JS 环境下仍能加载,避免白屏 - 不要用
document.write或动态appendChild—— 可能阻塞渲染或触发重排
与 rel="prefetch" 或 rel="preload" 其他资源混用时的坑
同一个 CSS 文件不能既被 preload 又被普通 stylesheet 引用,否则 Chrome 会记录两次网络请求(DevTools → Network → Filter: main.css),浪费带宽。
立即学习“前端免费学习笔记(深入)”;
- 检查 HTML 中是否残留旧的
<link rel="stylesheet" href="critical.css">标签 -
prefetch适用于低优先级资源(如下一屏 CSS),和preload语义冲突,混用会干扰加载调度 - HTTP/2 推送(
Link: </css/critical.css>; rel=preload; as=style)已逐步弃用,现代项目应优先走前端preload+ JS 注入路径
验证是否生效的三个检查点
别只看 Network 面板里有没有 200 —— 要确认它真正参与了首屏渲染:
- 在 Elements 面板中搜索
critical.css,确认对应link的rel已变成stylesheet(而非保持preload) - Performance 面板录制首屏加载,查看
Stylesheets解析时间是否明显前移(对比未预加载版本) - 禁用 JS 后刷新,确认
<noscript>内容仍能加载 —— 否则降级失败,首屏直接无样式
最容易被忽略的是 onload 执行时机和 rel 切换动作是否原子化;很多“预加载了但没效果”的问题,根源都在那一行 this.rel='stylesheet' 没跑成。

















