rel="preload"单独使用无效,因其仅下载CSS而不解析、不挂载,必须搭配as="style"和onload="this.onload=null;this.rel='stylesheet'"才能触发CSSOM构建并生效,且需<noscript>降级保障兼容性。

只加 rel="preload" 不会生效——它只下载不解析、不挂载,页面照样白屏或错乱。 必须搭配 as="style" 和 onload 动态切换 rel 值,否则就是“白忙活”。
为什么 rel="preload" 单独写没用
浏览器把 rel="preload" 当作“提前取货”,不是“立刻上架”。哪怕 Network 面板显示文件已下载完成,只要 rel 还是 "preload",CSS 就不会参与 CSSOM 构建,也不会影响渲染。
- 漏写
as="style"→ Chrome 按as="fetch"处理,可能被 CSP 拦截,或降级为低优先级请求 - 没写
onload或逻辑不完整 → 样式永远不会挂载,页面无样式 - 同时存在另一个
<link rel="stylesheet">→ Chrome 会发起两次请求,浪费带宽
onload 回调必须这样写
核心是让 preload 下载完成后立刻切换 rel,且防止重复执行。常见错误是把 this.onload=null 放在后面,导致 SPA 路由复用或刷新时触发多次设置,报错 Failed to set the 'rel' property。
-
this.onload=null必须写在回调最前,例如:onload="this.onload=null;this.rel='stylesheet'" - 不能用
onreadystatechange替代 —— 它在现代浏览器中不可靠,无法区分成功/失败 - 路径必须完全一致:带查询参数的也要对齐,
main.css?v=1.2和main.css?v=1.3在浏览器眼里是两个资源,preload 不会复用
服务端和兼容性容易被忽略的点
即使 HTML 写对了,服务端响应头或旧浏览器也可能让整个方案失效。
立即学习“前端免费学习笔记(深入)”;
- 服务端返回
Cache-Control: no-cache时,Chrome 可能直接跳过 preload,需检查响应头 - Safari 直到 iOS 16.4 / macOS 13.3 才支持
as="style",之前版本会降级为普通 fetch,优先级不提升 - IE 完全不支持
rel="preload",必须加<noscript><link rel="stylesheet" href="..."></noscript>降级 - 旧版 Edge(EdgeHTML)直接忽略
rel="preload",无 fallback 则样式丢失
真正起效的关键不在“写了多少 preload”,而在于是否切断了隐性阻塞链——比如非关键 CSS 里藏着 @import、未加 font-display: optional 的字体,或指向大图的 background-image。这些会在样式挂载后才开始拉取,悄悄拖慢交互就绪时间。


















