资源预加载概述
预加载技术允许开发者提前告知浏览器将要使用的资源,使浏览器能够更早地开始下载,减少用户等待时间。
| 类型 | 用途 | 优先级 |
|---|---|---|
| preload | 当前页面关键资源 | 高 |
| prefetch | 未来导航的资源 | 低 |
| preconnect | 提前建立连接 | - |
| dns-prefetch | 提前解析 DNS | - |
preload - 预加载关键资源
基本用法
<!-- 预加载关键字体 -->
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>
<!-- 预加载关键脚本 -->
<link rel="preload" href="/js/critical.js" as="script">
<!-- 预加载首屏图片 -->
<link rel="preload" href="/images/hero.webp" as="image">
<!-- 预加载关键 CSS -->
<link rel="preload" href="/css/critical.css" as="style">
关键说明: as 属性必须指定正确的资源类型,否则浏览器可能不会正确使用该资源,导致重复下载。
动态预加载
function preloadResource(href: string, as: string) {
const link = document.createElement('link')
link.rel = 'preload'
link.href = href
link.as = as
if (as === 'font') {
link.crossOrigin = 'anonymous'
}
document.head.appendChild(link)
}
// 根据用户行为预加载
button.addEventListener('mouseenter', () => {
preloadResource('/js/heavy-feature.js', 'script')
})
prefetch - 预取未来资源
页面级预取
<!-- 预取下一页 HTML -->
<link rel="prefetch" href="/about">
<!-- 预取下一页的资源 -->
<link rel="prefetch" href="/js/about-page.js" as="script">
智能预取策略
// 基于链接可见性预取
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const link = entry.target as HTMLAnchorElement
prefetchPage(link.href)
observer.unobserve(link)
}
})
})
document.querySelectorAll('a[href^="/"]').forEach(link => {
observer.observe(link)
})
function prefetchPage(href: string) {
const link = document.createElement('link')
link.rel = 'prefetch'
link.href = href
document.head.appendChild(link)
}
preconnect - 预连接
提前建立 TCP 连接、TLS 握手,减少请求延迟:
<!-- 预连接到关键第三方源 -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://cdn.example.com" crossorigin>
<link rel="preconnect" href="https://api.example.com">
使用场景
- 第三方字体服务
- CDN 域名
- API 服务器
- 统计分析服务
dns-prefetch - DNS 预解析
比 preconnect 更轻量,只做 DNS 解析:
<link rel="dns-prefetch" href="//analytics.example.com">
<link rel="dns-prefetch" href="//static.example.com">
preconnect vs dns-prefetch
<!-- 对于确定会用到的资源,两者结合使用 -->
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="dns-prefetch" href="//fonts.gstatic.com">
| 对比项 | preconnect | dns-prefetch |
|---|---|---|
| DNS 解析 | ✅ | ✅ |
| TCP 连接 | ✅ | ❌ |
| TLS 握手 | ✅ | ❌ |
| 浏览器支持 | 现代浏览器 | 广泛支持 |
在现代框架中使用
Nuxt 3 配置
// nuxt.config.ts
export default defineNuxtConfig({
app: {
head: {
link: [
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
{ rel: 'preload', href: '/fonts/main.woff2', as: 'font', type: 'font/woff2', crossorigin: 'anonymous' }
]
}
}
})
动态 Head 管理
// 在页面组件中
useHead({
link: [
{ rel: 'preload', href: product.value.image, as: 'image' }
]
})
最佳实践
- 不要过度预加载:只预加载确定会用到的关键资源
- 正确设置 as 属性:确保资源类型匹配
- 字体需要 crossorigin:即使同源也需要设置
- 监控效果:使用 DevTools 验证预加载是否生效
- 结合用户行为:基于鼠标悬停等行为智能预取
调试技巧
在 Chrome DevTools Network 面板中:
- preload 资源显示 Priority: High
- prefetch 资源显示 Priority: Lowest
- 检查是否有"unused preload"警告
正确使用预加载策略可以显著改善页面加载速度和用户体验。


