rel="preload" 仅触发高优先级下载,不解析、不挂载、不参与渲染;必须搭配 as="style" 和 onload="this.onload=null;this.rel='stylesheet'" 才生效,且需 兜底。

为什么只写 rel="preload" 没用
浏览器看到 <link rel="preload" href="main.css" as="style">,只会发起高优先级下载,但完全不解析、不挂载、不参与渲染。DOM 仍是无样式的,页面可能白屏或布局坍塌。
常见错误是只加 rel="preload",后面没跟任何 <link rel="stylesheet">,结果文件下了却压根没用上。
-
as="style"必须写,否则 Chrome/Firefox 会降级为普通 fetch,不设高优先级,也不校验 MIME 类型 - Safari 在 iOS 16.4 / macOS 13.3 之前根本不支持
as="style"的preload,只当普通资源下载 - 服务端若对 CSS 返回
Cache-Control: no-cache,Chrome 会跳过preload(认为没必要预取)
怎么写 onload 才真正生效
核心动作是:下载完成后,把同一个 <link> 的 rel 从 preload 改成 stylesheet。必须用 onload 回调,不能靠 onreadystatechange —— 它在现代浏览器中不可靠,且无法区分成功/失败。
标准写法:
<link rel="preload" href="critical.css" as="style" onload="this.onload=null; this.rel='stylesheet'"><noscript><link rel="stylesheet" href="critical.css"></noscript>
-
this.onload=null要写在最前,防 Chrome 某些版本重复触发onload -
href路径必须和<noscript></noscript>里的一致(包括查询参数:theme.css?v=2.1和theme.css?v=2.2是两个资源) -
<noscript></noscript>不是可选项,是必要兜底:JS 禁用时退回到传统阻塞加载,至少功能完整
哪些 CSS 适合用 preload+onload
只用于首屏关键样式,比如 base.css、header.css、critical.css。非关键 CSS(如动画、打印、主题切换)不该走这条路。
- 对非关键 CSS,用
media="print"+onload="this.media='all'"更轻量、兼容性更好 - 别对所有 CSS 都
preload:它占用高优先级带宽,反而挤占 JS 或首屏图片请求 - 如果非关键 CSS 里含
@font-face引了 2MB 字体,或background-image指向高延迟 CDN 图片,异步也救不了首屏——这些子资源会在样式挂载后才拉取 - 避免在非关键 CSS 里写
@import:它会同步阻塞该 CSS 的解析,形成隐蔽的二级阻塞链
容易被忽略的兼容性与边界问题
preload 在 IE 全系、旧版 Android WebView 中被静默忽略。问题不在“报错”,而在“什么也不做”——如果你没配 <noscript></noscript> 或 JS fallback,关键样式就彻底丢失。
- Safari 11.1+、Chrome 50+、Firefox 56+ 支持,但 Firefox 的
onload有时明显延迟,建议加超时兜底(例如 5s 后强制rel='stylesheet') - 动态切换
media值不会重新触发preload,已下载资源会缓存,但不会自动应用 - 不要依赖
document.currentScript判断插入位置,老版本 Android WebView 里它可能为null
真正难的不是写对那一行 onload,而是确保路径一致、降级可靠、子资源不拖后腿——漏掉任意一环,都可能让“异步加载”变成“白屏加载”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











