预加载标签并非越多越好,超过3–4个易挤占带宽拖慢首屏;应仅对阻塞渲染且浏览器发现太晚的字体、内联style中固定路径字体、首屏必需立即执行的小脚本进行preload,其余多为负优化。

预加载标签不是越多越好,超过 3–4 个就容易挤占关键资源带宽,反而拖慢首屏。真正要做的不是“加多少”,而是“加哪些”和“加得对不对”。
哪些资源必须 preload,哪些绝对不能
浏览器对 <link rel="preload"> 是无条件立即抓取,不排队、不协商、不看上下文。所以必须只留给三类资源:
- 阻塞渲染且浏览器发现太晚的字体:比如 CSS 中引用的
inter-latin.woff2,而 CSS 本身是<link rel="stylesheet">异步加载的 - 内联
<style></style>中直接用@font-face引用的字体文件(路径固定、无变量) - 首屏 JS 中立即执行、且无法通过
type="module"或defer自动调度的极少数脚本(如一个 5KB 的初始化逻辑)
以下全是反例,加了等于白加甚至负优化:
-
<link rel="preload" href="/js/chunk-<code>hash.js" as="script"> —— chunk 哈希不可预测,preload 不支持运行时拼接 -
<link rel="preload" href="/images/hero.jpg" as="image">—— 图片应走loading="lazy"+srcset,preload 会提前下载大图,用户还没滚动就占满带宽 -
<link rel="preload" href="/css/non-critical.css" as="style">—— 非首屏样式不该进 preload,应延迟加载或用media属性控制
as 属性写错会导致 preload 彻底失效
as 不只是语义标记,它决定请求头、缓存策略、优先级队列。写错就等于没写:
立即学习“前端免费学习笔记(深入)”;
-
as="fetch"或as="xmlhttprequest":浏览器不认识,直接忽略该 preload -
as="script"但资源实际是 JSON 接口:请求头缺Accept: application/json,可能被服务端拒绝或返回错误格式 -
as="font"但漏了crossorigin:字体跨域请求失败,控制台报CORS header 'Access-Control-Allow-Origin' missing
验证方法:打开 Chrome DevTools → Network → 找到该资源 → 查看 Initiator 列是否为 Preload Scanner;如果不是,说明没生效。
SSR/动态插入场景下如何避免误加
React/Vue 服务端渲染时用 helmet 或 head 指令动态注入 preload,极易把非当前页面资源也塞进去。比如用户访问 /dashboard,却 preload 了 /report 页面才用的图表库。
- 服务端必须基于真实路由和组件依赖树做静态分析,不能靠“所有可能用到的资源”列表硬塞
- 客户端 hydration 后,不要再重复插入相同
href的 preload 标签(Chrome 115+ 对同 URL 有去重,但旧版仍会双发) - 用
media属性做兜底:<link rel="preload" href="theme-dark.css" as="style" media="(prefers-color-scheme: dark)">,避免亮色模式下也加载暗色主题
最常被忽略的一点:preload 不是“让资源更快”,而是“让资源更早开始下载”。如果资源本身体积大、路径不稳定、或根本不在首屏路径上,它只会变成带宽黑洞。删掉第 4 个 preload,往往比优化前 3 个更有效。



















