是HTML中唯一标准、可控、不阻塞渲染的预加载方式,但仅负责提前下载,必须配合as属性(如as="script")、静态写入、onload激活等步骤才能生效,否则无效或重复请求。

直接说结论:用 <link rel="preload"> 是 HTML 中唯一标准、可控、不阻塞渲染的预加载方式;但它只负责“下载”,不负责“使用”,漏掉后续步骤等于白干。
为什么 <link rel="preload"> 必须写在 里且不能动态插入
浏览器在解析 HTML 的最早阶段(甚至还没构建 DOM 树)就扫描 中的 <link rel="preload">,立刻发起高优先级请求。如果用 JS 动态创建并 append 进去,此时解析早已完成,预加载失去意义——它会退化成普通 fetch,且可能被节流或延迟。
- 常见错误:在 React/Vue 组件
useEffect或mounted钩子中document.head.appendChild(preloadLink)→ 实际没提前 - 正确姿势:静态写死在 HTML 模板的
最顶部,越早越好 - 验证方法:Chrome DevTools → Network 面板 → 查看该资源的
Initiator列是否为parser(不是script或other)
as 属性填错会导致二次请求或失效
as 不是可选项,是强制要求。它决定浏览器如何设置请求头、缓存策略、CORS 行为和优先级。填错类型,比如把字体写成 as="image",浏览器可能忽略预加载,或等真正用到时再发一次带正确 as 的请求(即重复下载)。
- 字体必须用
as="font",且必须加crossorigin(即使同源),否则 Chrome/Safari 直接丢弃预加载结果 - CSS 必须用
as="style",JS 必须用as="script",图片必须用as="image" -
as="fetch"适用于fetch()调用的 API 接口,能提前建立连接并设置优先级,但需配合type="application/json"等 MIME 类型
预加载 CSS 后怎么让它真正生效
<link rel="preload" href="main.css" as="style"> 只下载不解析。若不手动触发应用,样式永远不会起作用。最简方案是用 onload 回调切换 rel:
立即学习“前端免费学习笔记(深入)”;
<link rel="preload" href="main.css" as="style" onload="this.rel='stylesheet'">
注意:onload 在资源下载完成时触发,但不保证 CSS 已解析完毕;如需更精细控制(比如等 DOM 就绪后才应用),可改用 JS 监听并插入普通 <link rel="stylesheet"> 标签。
- 别写两遍:既
preload又另起一行<link rel="stylesheet">→ 大概率触发重复请求(尤其 Safari) - 异步脚本场景:若 CSS 是供某个
async脚本使用的,预加载后可在脚本里动态创建<link rel="stylesheet">,避免阻塞 - 兼容性兜底:旧版浏览器不支持
preload,onload不会执行,此时需靠 fallback 的普通<link rel="stylesheet">保证可用
什么时候不该用 preload,反而会拖慢页面
预加载本质是“抢带宽”。如果资源不是当前导航生命周期内确定要用的,或者体积大、优先级低,preload 就是在给首屏渲染挖坑。
- 用户交互后才加载的模块(如点击弹窗才载入的表单组件 JS)→ 改用
<link rel="prefetch">,交给浏览器空闲时处理 - 第三方统计/埋点脚本 → 它们本就不该影响首屏,
preload会挤占关键资源带宽 - 未做 code-splitting 的 800KB
vendor.js→ 即使as="script",也会让 Chrome 以最高优先级抢占 TCP 连接,拖慢 CSS/首屏图 - 懒加载图片(
loading="lazy")→ 和preload语义完全相反,混用等于自相矛盾
最容易被忽略的一点:预加载本身不解决渲染阻塞。比如预加载了字体,但 CSS 里没写 font-display: swap,文本依然白屏等待——preload 只是把文件拉下来,能不能“不卡”得靠配套策略。



















