rel="preload"单独使用无效,因其仅下载css而不解析应用;必须配合onload回调将rel改为"stylesheet"才能生效,且需设as="style"、清空onload防止重复执行,并用降级。

不能只靠 rel="preload" 让 CSS 不阻塞首屏渲染——它只提前发请求,不改变阻塞逻辑;必须配合 onload 切换 rel 类型,否则样式永远不会生效。
为什么 rel="preload" 单独用没用
浏览器对 rel="preload" 的处理是:发起网络请求、下载资源、存入内存缓存,但**完全跳过解析和应用步骤**。它不参与 CSSOM 构建,也不触发任何渲染阻塞或释放。你看到 Network 面板里文件下载完成了,但页面还是没样式——因为 rel 值仍是 "preload",不是 "stylesheet"。
常见错误写法:<link rel="preload" href="main.css" as="style"> —— 这行代码等同于“偷偷下个文件放着”,对渲染零影响。
- 必须加
onload回调,并在其中把rel改成"stylesheet" - 必须设
as="style",否则 Chrome 会忽略该 preload(不识别为样式资源) - IE 完全不支持
rel="preload",需降级 fallback(如<noscript></noscript>内补普通link)
onload 回调必须手动清空
onload 是一次性事件,但如果不显式置空,某些场景下(比如用户刷新、SPA 路由复用节点)可能被重复触发,导致 rel 被反复设置、甚至报错(rel 已是 "stylesheet" 时再设会失败)。
正确写法示例:
<link rel="preload" href="non-critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'"><noscript><link rel="stylesheet" href="non-critical.css"></noscript>
-
this.onload=null必须写在回调最前,防止二次执行 -
<noscript></noscript>是必要降级:JS 被禁用时,仍能加载样式(虽会阻塞,但至少功能完整) - 不要用
onreadystatechange替代onload——它在现代浏览器中不可靠,且无法区分加载成功/失败
非关键 CSS 的路径和依赖仍会影响首屏
即使你把 non-critical.css 延迟加载了,如果它内部用 @font-face 引了 2MB 的 woff2 字体,或 background-image 指向一个高延迟 CDN 图片,这些子资源会在样式表挂载后才开始拉取——而它们的下载会挤占首屏 JS/CSS 的带宽,拖慢交互就绪时间。
- 检查非关键 CSS 中是否含字体、图标、大图等渲染阻塞型资源
- 若必须引入,优先用
font-display: optional或图片懒加载(loading="lazy")缓解 - 避免在非关键 CSS 里写
@import——它会同步阻塞该 CSS 的解析,形成隐蔽的二级阻塞链
preload 不是越多越好,得看资源实际使用概率
rel="preload" 会抢占 TCP 连接、带宽和 HTTP/2 流,如果预加载了用户根本不会访问的样式(比如暗色主题、打印样式、后台管理页 CSS),反而会推迟关键资源(如首屏 JS、关键 CSS)的下载起始时间。
判断是否该 preload 的依据只有一个:该 CSS 在当前 HTML 文档生命周期内,是否 100% 会被用到?
- 首屏必现组件的样式 → 可内联,或
preload + onload(慎用,优先内联) - 用户点击后才出现的模态框、抽屉菜单样式 → 适合
preload + onload - 设备媒体查询才匹配的样式(如
media="(min-width: 1200px)")→ 不要 preload,用原生media属性更轻量
最容易被忽略的是:你写了 preload,却没验证它是否真比普通 link 更早开始下载——打开 DevTools > Network,对比 Start Time 和 End Time,确认它确实抢在关键 JS 之前发起了请求。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











