四种预取机制
浏览器提供了多种预取机制,帮助提前加载资源:
| 机制 | 作用时机 | 优先级 | 使用场景 |
|---|---|---|---|
| preload | 当前页面 | 高 | 当前页面必需的资源 |
| prefetch | 未来页面 | 低 | 下一个页面需要的资源 |
| preconnect | 当前页面 | 高 | 提前建立连接 |
| prerender | 未来页面 | 高 | 提前渲染整个页面 |
Preload
提前加载当前页面需要的资源:
<!-- 提前加载关键 CSS -->
<link rel="preload" href="/styles.css" as="style">
<!-- 提前加载关键 JS -->
<link rel="preload" href="/app.js" as="script">
<!-- 提前加载字体 -->
<link rel="preload" href="/fonts/myfont.woff2" as="font" crossorigin>
何时使用 Preload
- 首屏渲染必需的资源
- 当前页面需要但 HTML 解析时不会自动发现的资源
- 字体(浏览器不会自动发现跨域字体)
as 属性
必须指定正确的 as 值:
style:CSSscript:JavaScriptfont:字体文件image:图片fetch:API 请求
Prefetch
提前获取未来页面需要的资源:
<!-- 预测用户下一步会访问的页面资源 -->
<link rel="prefetch" href="/next-page.css">
<link rel="prefetch" href="/next-page.js">
与 Preload 的区别
- preload:当前页面必需,高优先级
- prefetch:未来页面需要,低优先级
使用场景
// 搜索场景:用户输入时预取搜索结果
searchInput.addEventListener('input', () => {
const query = searchInput.value;
if (query.length > 2) {
// 预取搜索建议
const link = document.createElement('link');
link.rel = 'prefetch';
link.href = `/api/suggest?q=${encodeURIComponent(query)}`;
document.head.appendChild(link);
}
});
Preconnect
提前建立网络连接:
<!-- 提前建立与 CDN 的连接 -->
<link rel="preconnect" href="https://cdn.example.com">
<!-- 包括 TLS 握手 -->
<link rel="preconnect" href="https://cdn.example.com" crossorigin>
使用场景
- 第三方域名(字体、API、分析工具)
- CDN 域名
- 任何你知道会访问的域名
dns-prefetch vs preconnect
dns-prefetch:只解析 DNSpreconnect:DNS + TCP 握手 + TLS 握手
<!-- 基础版:只 DNS 解析 -->
<link rel="dns-prefetch" href="https://cdn.example.com">
<!-- 完整版:DNS + 连接 -->
<link rel="preconnect" href="https://cdn.example.com">
Prerender
提前渲染整个页面:
<!-- 预测用户下一步会访问的页面 -->
<link rel="prerender" href="/next-page.html">
页面会在后台完全渲染(包括执行 JavaScript),当用户导航到该页面时,内容已经准备好了。
使用注意
- 会消耗大量资源和带宽
- 如果预渲染的页面有音频/视频,会自动播放
- 可能导致隐私问题(执行 JS)
实际应用场景
场景一:字体加载优化
<!-- 先 preconnect,再 preload 字体 -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preload" href="/fonts/myfont.woff2" as="font" crossorigin>
场景二:路由懒加载
// React 路由配置
const routes = [
{
path: '/dashboard',
component: lazy(() => import('./Dashboard'))
}
];
// 在 Dashboard 路由渲染前预取
<Link
to="/dashboard"
onMouseEnter={() => {
const link = document.createElement('link');
link.rel = 'prefetch';
link.href = '/dashboard-chunk.js';
document.head.appendChild(link);
}}
>
Go to Dashboard
</Link>
这一章想说的
四种预取机制各有用途:
- preload:提前加载当前页面必需的资源
- prefetch:提前获取未来页面需要的资源
- preconnect:提前建立网络连接
- prerender:提前渲染整个页面(谨慎使用)
合理使用预取可以显著提升用户体验,但不要滥用——预取会消耗带宽和资源。