好的,我们来详细梳理一下前端中的 preload 和 prefetch。它们是两种非常重要的资源提示(Resource Hints),用于优化页面加载性能和用户体验,但目的和应用场景有显著区别。
核心概念就一句话:
- Preload:加载当前页面必定需要的资源。(高优先级,当前用)
- Prefetch:加载未来页面可能需要的资源。(低优先级,未来用)
下面我们分别详细解释。
1. Preload
preload 的核心思想是 “提前加载,即刻使用”。它告诉浏览器,当前页面非常需要某个资源,请以高优先级尽快获取它。浏览器会为此资源分配高优先级,但不会执行它(比如脚本不会执行,样式表不会应用),只是提前缓存到本地。当页面真正需要用到该资源时,它已经在缓存里了,可以直接从磁盘读取,从而消除了网络请求的延迟。
如何使用
主要通过 `` 标签的 rel="preload" 属性,并配合 as 属性来指定资源类型。
<link rel="preload" href="critical-font.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="hero-image.jpg" as="image">
<link rel="preload" href="main.js" as="script">
<link rel="preload" href="theme.css" as="style">关键特性与使用场景
- 高优先级:浏览器会以较高的优先级(
High)来获取这些资源。 - 必须指定
as属性:这非常重要。它告诉浏览器资源类型,以便:- 设置正确的请求优先级。
- 应用正确的内容安全策略(CSP)。
- 浏览器能判断资源是否在缓存中已存在,避免重复请求。
- 用于关键资源:非常适合用于渲染首屏内容所必需的关键资源,例如:
- 首屏的大型图片或 Web字体。
- 关键的CSS或JS文件。
- 首屏视频 poster 图。
- 浏览器支持:现代浏览器普遍支持。
最佳实践示例
一个典型场景是预加载Web字体。字体文件通常藏在CSS中,浏览器要很晚才能发现并请求,容易导致文字样式闪烁(FOIT/FOUT)。使用 preload 可以强制浏览器提前请求字体。
<!-- 提前请求字体,即使CSS还没解析到 -->
<link rel="preload" href="myfont.woff2" as="font" type="font/woff2" crossorigin>
<!-- 正常的CSS引用 -->
<link rel="stylesheet" href="styles.css">在 styles.css 中定义了 @font-face { font-family: 'MyFont'; src: url(myfont.woff2) format('woff2'); }。这样字体请求会和CSS请求几乎同时发出,大大减少了字体加载带来的布局偏移和样式闪烁。
2. Prefetch
prefetch 的核心思想是 “闲时加载,未来使用”。它告诉浏览器,这个资源用户可能在未来的导航中会用到(比如下一个页面)。浏览器会在空闲时间(idle time)以最低优先级(Lowest)获取并缓存这个资源。当用户真正访问下一个页面时,如果该页面需要这个资源,它已经被缓存了,可以立即使用,从而大幅提升下一个页面的加载速度。
如何使用
同样使用 `` 标签,但 rel="prefetch"。
<link rel="prefetch" href="next-page.js">
<link rel="prefetch" href="next-page.css">
<link rel="prefetch" href="avatar.png">关键特性与使用场景
- 低优先级:浏览器只在带宽空闲时才会加载它,绝不会影响当前页面的关键资源加载。
- 用于未来导航:主要用于优化用户下一步可能去往的页面的体验。例如:
- 在电商首页,预取用户最可能点击的“热门商品”详情页的资源。
- 在长文章的第一页,预取第二页的资源。
- 预取用户鼠标悬停的链接资源(结合一些简单的JavaScript预测)。
- 缓存时间: prefetch 的资源会被缓存一段时间(取决于浏览器,通常5分钟左右),供后续页面使用。
- DNS Prefetch:还有一个相关的
dns-prefetch,只专门用于提前进行DNS解析,适用于跨域域名,开销极小。html<link rel="dns-prefetch" href="https://api.example.com">
对比总结表
| 特性 | Preload | Prefetch |
|---|---|---|
| 核心目的 | 提前加载当前页面关键资源 | 提前加载未来页面可能需要的资源 |
| 加载时机 | 立即,以高优先级获取 | 空闲时,以低优先级获取 |
| 优先级 | 高 (High) | 非常低 (Lowest) |
| 浏览器缓存 | 缓存到磁盘,供当前页面使用 | 缓存到磁盘(或HTTP缓存),供未来页面使用 |
| 使用场景 | 字体、首屏大图、关键CSS/JS | 下一个页面的脚本、样式、图片等 |
| 语法示例 | <link rel="preload" href="a.js" as="script"> | <link rel="prefetch" href="b.js"> |
常见误区与注意事项
- 不要滥用 Preload:如果对非关键资源使用
preload,会挤占网络带宽,反而损害当前页面的性能,因为它会以高优先级抢夺关键资源(如自身JS/CSS)的下载时间。只预加载真正关键的资源。 - Preload 和 Prefetch 都会请求资源:它们都会真实地发起HTTP请求。如果资源在缓存中已存在(例如通过Service Worker缓存),浏览器可能不会再次请求。
- Prefetch 是一种预测:它基于你对用户行为的预测。如果预测错误,用户根本没有访问下一个页面,那么这次预取就是一种带宽浪费。
- 双请求问题:如果你预取了一个资源(如
script.js),而下一个页面也确实引用了它,大部分现代浏览器会从缓存中读取,而不会发起第二次请求。但某些老旧浏览器或特殊场景下可能仍会验证缓存,需要注意。
总结
选择 preload 还是 prefetch,完全取决于你的目标:
- 想让当前页面加载更快?找出渲染阻塞的关键资源,使用
preload。 - 想让用户下一个页面的体验如丝般顺滑?预测用户行为,使用
prefetch。
正确使用这两种资源提示,可以显著提升网站的性能感知和用户体验。