prefetch 和 preload 有什么区别?
面试结论
preload 和 prefetch 都是通过 <link> 向浏览器提供的资源提示,但它们表达的意图不同:
preload表示“当前页面很快就会用到这个资源”,浏览器会尽早以较高优先级获取;prefetch表示“后续页面可能会用到这个资源”,浏览器通常只在当前页面空闲时以较低优先级获取。
因此,首屏关键字体、LCP 图片或被 CSS/JavaScript 较晚发现的关键资源适合 preload;下一路由的 chunk、下一篇文章的数据等非当前页面必需资源才适合 prefetch。两者只是提示,不保证一定下载;滥用 preload 还会与真正关键的资源争抢带宽。
核心对比
“通常较高”不是协议承诺的固定优先级。浏览器会结合资源类型、页面状态、网络和省流策略自行调度。
浏览器内部发生了什么?
正常情况下,浏览器只有解析到 <img>、<script>、CSS 中的 @font-face,或等 JavaScript 动态创建请求后,才能发现资源。发现过晚会让关键资源错过下载窗口。
资源提示把发现时机提前到 HTML <head>:
preload 解决“当前页关键资源发现太晚”的问题;prefetch 利用当前页的空闲网络时间,降低未来页面的等待。它们不会替代真正的 <script>、stylesheet 或 <img>:只有资源的实际消费者出现后,脚本才会执行、样式才会应用、图片才会渲染。
最小示例
preload:提前加载当前页关键字体和 LCP 图片
字体通常到 CSS 被解析并匹配到文本后才会请求,preload 把请求提前。字体即使与页面同源,也通常按字体请求的 CORS 模式获取,所以预加载字体一般要带 crossorigin;否则实际使用时可能无法复用,造成二次下载。
fetchpriority="high" 是额外的优先级提示,不等同于 preload。前者影响请求优先级,后者主要让浏览器更早发现请求,两者可以配合,但都不应滥用。
响应式图片要保证预加载候选与 <img> 的选择一致,可以使用 imagesrcset 和 imagesizes,否则浏览器可能先下载一张不合适的图片:
prefetch:准备可能访问的下一路由
这段代码只是建议浏览器低优先级获取文件。当前页不会因此执行 product-detail.js;用户真正进入商品详情页、应用再 import() 同一 URL 时,才可能从缓存中复用它。
真实 SPA 通常由路由器或构建工具根据链接可见、鼠标悬停、网络状况等条件动态插入提示。上面的代码只用于演示浏览器机制,不代表框架内部实现。
as 为什么重要?
preload 的 as 告诉浏览器资源的目标类型,例如 script、style、image、font 或 fetch。浏览器据此设置请求优先级、Accept 请求头、内容安全策略以及缓存分区。
下面的预加载可能无法被实际字体请求正确复用:
判断是否复用不能只看 URL。请求模式、凭证模式和资源类型也要匹配。例如预加载跨域接口数据时,提示和实际 fetch 应使用一致的 CORS/凭证语义:
即使配置正确,缓存复用仍受响应缓存头、缓存分区和浏览器实现影响,不能把资源提示当作永久缓存方案。
如何选择?
先问资源服务于哪个页面:
- 当前页面渲染或交互很快就需要,而且正常发现得较晚:考虑
preload。 - 只是用户下一步很可能需要,当前页面不依赖:考虑
prefetch。 - 只想提前完成 DNS、TCP 或 TLS 建连,不想下载具体资源:使用
dns-prefetch或preconnect。 - JavaScript 模块及其依赖图需要预加载:优先考虑
modulepreload,而不是普通preload as="script"。
工程实践与验证
不要仅凭“感觉关键”添加提示。应先用 Chrome DevTools 的 Network、Performance 面板或 WebPageTest 验证:
- 资源原本是否发现得晚;
- 添加后请求开始时间是否提前;
- Initiator、Priority 和 Size(缓存命中)是否符合预期;
- 是否出现同一 URL 的两次请求;
- LCP 等用户指标是否改善;
- 弱网下是否推迟了 CSS、主脚本等更重要的资源。
生产环境通常只 preload 极少数经过测量确认的首屏资源。对于 prefetch,还应考虑用户是否开启省流模式、网络质量、命中概率和资源大小;浏览器可能基于这些条件降低优先级或完全忽略提示。
服务端也可以通过 HTTP Link 响应头发送资源提示,使浏览器在解析 HTML 前发现资源,但是否支持、何时处理以及优先级仍由客户端决定:
常见陷阱
- 把 preload 当成执行标签:它只获取资源,仍需
<script>、<link rel="stylesheet">、<img>或fetch()消费。 - 预加载所有首屏文件:过多高优先级请求会争抢连接和带宽,反而让真正关键资源变慢。
as填错或遗漏:请求上下文不同可能导致资源不能复用,甚至被安全策略拦截。- 字体忘记
crossorigin:预加载与实际字体请求模式不匹配,常造成重复下载。 - 预加载响应式图片的错误候选:预加载一张、
srcset又选择另一张,会浪费流量。 - 把 prefetch 当成可靠缓存:它是可被忽略的提示,缓存也可能在导航前被清理或因缓存策略而无法复用。
- 混淆
prefetch与dns-prefetch:前者下载具体资源,后者只提前做 DNS 解析。 - 忽略 URL 一致性:查询参数、重定向、凭证模式等差异都可能破坏复用。
模拟面试官深挖
1. 两者会阻塞 HTML 解析吗?
不会。它们通过 link 发起提示请求,HTML 解析可以继续;但下载会占用网络资源,间接影响其他请求。
为什么问:检查是否把“高优先级下载”和“解析阻塞”混为一谈。回答重点:CPU 解析阻塞与网络竞争是两个维度。
2. preload 下载的 JavaScript 会立即执行吗?
不会。还要由 <script> 或动态导入真正消费它。preload 只负责提前获取。
为什么问:检查是否理解资源获取和资源执行的边界。回答重点:下载不等于执行。
3. 为什么 preload 必须正确设置 as?
浏览器需要用它确定资源类型、请求头、优先级、安全策略和缓存上下文;填错可能无法被真实请求复用。
为什么问:从 API 定义追到请求调度和缓存匹配。回答重点:as 不只是描述信息。
4. 为什么字体 preload 常要加 crossorigin?
字体获取通常使用 CORS 请求模式。提示请求与 CSS 触发的真实字体请求模式不一致时,缓存条目可能不能复用。
为什么问:考察重复下载这一高频工程问题。回答重点:同 URL 不代表同请求上下文。
5. preload 与 fetchpriority="high" 有什么区别?
preload 让浏览器更早发现资源;fetchpriority 提示浏览器调整已发现资源的相对优先级。它们解决不同问题,可以配合使用。
为什么问:考察对“发现时机”和“调度优先级”的拆分。回答重点:不要把两者视为同义词。
6. prefetch 为什么不保证生效?
它只表达低紧迫度的未来需求。浏览器可根据网络、省流模式、页面状态和自身策略决定降级或忽略。
为什么问:避免把资源提示描述为强制指令。回答重点:提示的控制权在浏览器。
7. preload、prefetch、preconnect 如何选?
当前页迟发现的关键资源用 preload;未来可能使用的具体资源用 prefetch;只想提前建立到第三方源的连接用 preconnect。
为什么问:考察相似概念的边界。回答重点:分别对应当前资源、未来资源和连接准备。
8. 如何证明添加 preload 后真的变快了?
对比添加前后的请求开始时间、优先级、重复请求、关键资源竞争和 LCP 等指标,并在弱网及真实用户环境验证。如果只提前了请求却没有改善用户指标,甚至挤压关键 CSS,就应删除或调整。
为什么问:考察能否把知识用于生产环境。回答重点:以请求瀑布和用户指标验证,不以标签数量判断优化效果。
常见错误回答
- “
preload是同步加载,prefetch是异步加载。”两者都不会同步阻塞 HTML 解析;差异主要是使用时机与调度意图。 - “
preload的优先级永远最高。”实际优先级由浏览器结合资源类型和页面状态决定。 - “只要 URL 一样就肯定不会重复下载。”请求模式、凭证、
as、缓存头等不一致仍可能导致不能复用。 - “
prefetch能保证下一个页面秒开。”用户可能不导航,浏览器可能不下载,缓存也可能无法命中。 - “性能优化就应该把所有资源 preload。”这会制造带宽竞争,是典型的负优化。
总结
核心关键词:当前页与未来页、发现时机、请求优先级、缓存复用、浏览器提示。
一句话本质:preload 提前暴露当前页的关键请求,prefetch 用空闲机会为可能发生的未来请求做准备。
面试时可以按三个层次回答:
- 1 分钟:给出当前页/未来页、优先级和典型场景的对比。
- 3 分钟:补充只下载不执行、
as、字体 CORS、滥用导致带宽竞争。 - 10 分钟:展开浏览器发现与调度链路、缓存匹配、
modulepreload/preconnect边界,以及如何用网络瀑布和 LCP 验证。

