根本原因是preload只下载不解析应用,必须通过onload动态切换rel为stylesheet才能生效;若未切换或as="style"缺失,则CSS仅下载不生效。

rel=preload 为什么不能直接用在 上?
因为浏览器对 rel="preload" 和 rel="stylesheet" 的处理逻辑完全不同:前者是“提前获取资源”,不执行解析或应用;后者是“获取并立即阻塞渲染、解析并应用”。如果写成 <link rel="preload" href="style.css" as="style">,浏览器会下载 CSS,但不会解析它——你得手动触发加载,否则样式永远不会生效。
正确写法:preload + onload 动态注入 link 标签
必须配合 JavaScript,在 preload 完成后,创建一个 rel="stylesheet" 的 <link> 并插入 DOM。关键点:
-
as="style"必须显式声明,否则 Chrome 会降级为as="fetch",导致优先级错误、CSP 拦截或不触发预加载 - 监听
link.onload(不是onload事件冒泡到 window),避免 race condition - 不要用
link.addEventListener('load', ...),部分旧版 Safari 不支持load事件在<link>上触发
示例:
<link rel="preload" href="/critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'"> <noscript><link rel="stylesheet" href="/critical.css"></noscript>
哪些 CSS 真的适合 preload?
只限首屏强依赖、体积小、无跨域或 CSP 风险的内联关键 CSS 提取文件。常见误用:
立即学习“前端免费学习笔记(深入)”;
- 整个
main.css(体积大、含非首屏规则、可能含 @import)→ 拖慢关键路径,挤占带宽 - CDN 域名与当前页不同且未配
crossorigin→ 预加载失败静默丢弃(无报错) - 用了
@font-face或图片 URL 但未提前preload对应资源 → 字体闪动或背景图延迟渲染
推荐做法:用工具(如 critters 或 mini-css-extract-plugin + 自定义 critical CSS 提取)生成独立的 critical.css,再对其 preload。
兼容性与 fallback 要怎么写才不翻车?
rel="preload" 在 Safari 11.1+、Chrome 50+、Firefox 64+ 支持;IE 完全不支持。所以必须有降级路径:
- 永远搭配
<noscript>内的普通<link rel="stylesheet">,确保 JS 关闭时仍能加载 - 不要依赖
document.write或动态insertAdjacentHTML注入样式 —— 可能破坏 FOUC 或触发重复加载 - 如果项目用了 HTTP/2 Server Push,注意它和
preload叠加可能导致重复传输(现代 Chrome 已自动去重,但旧版需验证)
真正容易被忽略的是:preload 的 CSS 文件若带查询参数(如 ?v=1.2.3),而服务器没正确设置缓存头(Cache-Control: public, max-age=31536000),会导致每次都被当作新资源重新下载。


















