rel="preload"仅下载不解析不应用,必须配as="style"和onload动态改rel为"stylesheet"才生效;漏写任一环节会导致白屏、重复请求或CSP拦截。

写了 rel="preload" 为什么 CSS 还不生效
因为 rel="preload" 只负责下载,不解析、不应用。浏览器把它当作“提前存进缓存的文件”,不会自动挂载为样式表。即使你写了 ,DOM 渲染时照样没样式——这是设计行为,不是 bug。
-
as="style"必须显式写,漏掉或写成as="stylesheet"就静默降级为低优 fetch - 不能同时存在另一个
,路径稍有差异(比如多一个斜杠、大小写不同)就会触发二次请求 - 预加载完成前,
onload事件不会触发;若 JS 被阻塞或禁用,切换逻辑就卡住
必须用 onload 动态切换 rel 才能真正启用
最小可行写法是把切换逻辑直接写在 标签里,靠浏览器原生事件驱动,不依赖外部脚本:
<link rel="preload" href="/css/critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
-
this.onload=null是关键:防止某些浏览器重复触发onload(尤其在重试或缓存复用场景下) - 路径必须完全一致:包括协议、域名、路径分隔符、查询参数,否则缓存不复用
- 建议加
保底,避免 JS 禁用时白屏
常见失效信号:Network 面板里怎么看
别只看有没有那个 标签,打开 Chrome DevTools → Network → 刷新页面 → 筛选目标 CSS 文件名,重点看三列:
-
Initiator列显示preload(不是parser或script)→ 表示被识别 -
Priority列是Highest或High→ 表示优先级提升成功 -
Timing的Start Time比未加preload时明显提前(通常快 200–600ms)→ 实际收益可测 - 如果
Initiator是(other)或状态码是404/canceled,大概率是路径错、服务不可达,或被 HTTP/2 Push 干扰
容易被忽略的兼容性细节
看似简单的一行标签,实际受多个隐性条件制约:
-
必须静态写在最前面,紧贴后或前;动态插入(如document.createElement('link'))完全无效 - 字体和 CSS 共用同一份 CDN?仍要给字体加
crossorigin,而 CSS 不需要——类型决定策略,不是域名决定 -
type属性对 CSS 非必需,但若服务端返回 MIME 是text/css,而你写了type="application/css",部分浏览器可能拒绝缓存复用
真正难的不是写对标签,而是确保 as、路径、CORS、时机、后续挂载全部咬合。少一环,就只是多发了一次无意义的请求。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











