rel="preload"仅对首屏立即需用且浏览器发现太晚的资源有效,必须置于<meta charset>后、<title>前,as值须精准匹配资源类型并配合onload等机制才能生效,否则无效甚至拖慢性能。

rel="preload" 在大型应用里不是“加了就快”,而是只对首屏立即要用、但浏览器发现太晚的资源有效;加错位置、漏写 as、路径不一致,等于白写。
必须放最前,且紧贴后
浏览器在 HTML 解析阶段遇到 <link rel="preload"> 就立刻发起请求,不等 DOM 构建。放在 <body> 里、用 JS 动态插入、或塞在 <link rel="stylesheet"> 后面,都会让关键字体或主 Bundle 错过最佳下载窗口——实测延迟 200–800ms 是常态。
- ✅ 正确位置:
<meta charset="utf-8">后、<title>前 - ❌ 错误操作:用
document.createElement('link')插入,哪怕 append 到head也无效 - ⚠️ 注意:
rel="preload"不阻塞渲染,但会抢占带宽;若放得太晚,它反而挤占了真正首屏资源的通道
as 属性不是可选,写错等于没写
as 决定浏览器是否把它当高优资源处理。漏写、写成 as="fetch" 或 as="module",Chrome Network 面板里 Priority 就显示为 Low,和普通 fetch 无异;更糟的是,后续 <script src="main.js"> 还会重新发一次请求。
- 主 Bundle 必须写
as="script",不能省略 - 字体必须配
as="font"+crossorigin(即使同源);否则加载完也不生效 - CSS 必须写
as="style",且需配合onload="this.onload=null;this.rel='stylesheet'"才能真正应用 - 如果主 Bundle 带
integrity,<link rel="preload">也得带上相同值,否则缓存不复用
别对动态 import() 的 chunk 写 preload
Webpack/Vite 生成的 feature.abc123.js 这类分片路径是运行时才确定的,HTML 解析阶段根本无法静态识别。硬写 <link rel="preload" href="feature.abc123.js"> 只会导致构建后 404,或即使命中,浏览器也不会把 preload 下载结果关联到后续 import() 请求——它们属于不同缓存上下文。
立即学习“前端免费学习笔记(深入)”;
- ❌ 常见错误:首页 HTML 里手动 preload 所有路由 chunk,Lighthouse 评分暴跌
- ✅ 正确做法:对「用户即将进入」的模块,用
rel="prefetch";它会在空闲时低优先级拉取 - ✅ 对 ES 模块主入口(含静态
import链),改用rel="modulepreload";它会递归预取所有依赖,且不加as - ⚠️ 动态插入 preload link 仅限极特殊场景(如设备检测后加载高清逻辑),且 href 必须是完整静态路径,不能含变量
验证是否真起作用,只看 Network 面板三个字段
写了不等于生效。打开 Chrome DevTools → Network 面板,筛选并确认以下三点:
- Initiator 列必须显示为
preload(不是parser或script) - Priority 列必须是 Highest(
Low说明as漏了或写错) - 状态码应为
200(from memory cache)或304,而非重复请求的200(说明缓存未复用)
跨页面预加载永远别用 rel="preload"——它生命周期只绑定当前页,跳转即失效。真正要优化下一页,得靠 rel="prefetch" + rel="preconnect" 组合,且后者必须加 crossorigin 才在 Safari 生效。



















