必须显式声明as="style"并配合onload="this.rel='stylesheet'",否则preload仅下载不应用;需添加降级且href路径严格一致,media属性仅控制下载时机而非应用。

rel="preload"不加as="style"等于白写
浏览器看到rel="preload"但没as="style",会按as="fetch"处理——优先级拉低、可能被 CSP 拦截、甚至被降级为普通 fetch 请求。结果就是 CSS 文件下了,但压根不进 CSSOM,页面照样白屏或样式错乱。
必须显式声明as="style",才能让浏览器以样式表的语义去调度请求、分配高优先级、正确复用缓存。
-
href路径要和后续实际挂载的<link rel="stylesheet">完全一致(含查询参数),否则缓存不命中 - 不要写成
as="css"或as="text/css"——这些不是合法值,浏览器会忽略 - 如果用了 HTTP/2 Server Push,
as="style"也是必需的,否则推送资源不会被识别为样式表
onload里改rel="stylesheet"才是关键动作
rel="preload"只负责“下载”,不负责“应用”。漏掉onload逻辑,就等于把货运到仓库门口却不卸货——文件在缓存里躺着,页面永远等不到样式。
最小可行写法是:
<link rel="preload" href="/css/critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
这段 JS 的作用很具体:
-
this.rel='stylesheet'把 link 节点转为可解析的样式表节点 -
this.onload=null防 Safari 旧版重复触发 onload(尤其在缓存命中时) - 必须写在
里,且不能依赖外部 JS —— 外部脚本加载慢或失败会导致样式永久不挂载
没加
IE 全系、部分 Android WebView、早期 Safari 都不支持rel="preload",它们会直接忽略该标签。如果你只靠 preload,这些环境里critical.css根本不会加载。
降级不是可选项,是必选项:
<noscript><link rel="stylesheet" href="/css/critical.css"></noscript>
注意两点:
-
<noscript></noscript>必须紧跟在 preload 标签后面,保证顺序和 DOM 插入时机一致 - 不要用 JS 动态插入
<link rel="stylesheet">来 fallback——它可能阻塞解析,或因执行时机晚于渲染导致 FOUC - 某些构建工具(如 Webpack 的 MiniCssExtractPlugin)默认生成多个
<link>,容易和 preload 冲突,需手动去重
media 属性控制“是否下载”,不是“是否应用”
media写在 preload 标签上,只影响请求是否发起,不影响后续挂载行为。比如:
<link rel="preload" href="print.css" as="style" media="print">
这段代码的意思是:“只在用户打开打印预览时才下载 print.css”。但它一旦被下载,就不会自动变成rel="stylesheet",仍需配套onload逻辑或另一个带media="print"的<link rel="stylesheet">来真正启用。
常见误用:
- 写
media="(min-width: 768px)"却没配对应的<link rel="stylesheet">→ 小屏设备没样式,大屏设备样式延迟应用 - 动态切换
media值(如 JS 改link.media)→ 不会重新触发 preload,已缓存资源也不会自动应用 - 把非关键 CSS(如后台管理页样式)也 preload → 占用首屏带宽,得不偿失
真正需要关注的,是那个onload回调里是否被执行——它决定了样式到底上没上架,而不是 preload 标签有没有被写出来。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











