Prefetch 与 Preload
一、核心概念解析
特性 | Preload | Prefetch |
---|---|---|
核心目的 | 当前页面关键资源优先加载 | 未来页面资源预先获取 |
加载时机 | 立即高优先级加载 | 浏览器空闲时低优先级加载 |
缓存位置 | HTTP 缓存 (memory cache) | HTTP 缓存 (disk cache) |
资源类型 | 当前页面必需资源 | 未来页面可能使用资源 |
典型场景 | 首屏字体/关键 CSS/首图 | 下一页 JS/图片/数据 |
二、使用方式详解
1. HTML 声明方式
<!-- Preload 当前页面关键资源 -->
<link rel="preload" href="critical.css" as="style" />
<link
rel="preload"
href="hero-image.webp"
as="image"
imagesrcset="img-1x.jpg 1x, img-2x.jpg 2x"
/>
<link rel="preload" href="app.js" as="script" />
<!-- Prefetch 未来页面资源 -->
<link rel="prefetch" href="next-page.js" as="script" />
<link rel="prefetch" href="product-data.json" as="fetch" crossorigin />
2. HTTP Header 方式
# Preload 响应头
Link: </critical.css>; rel=preload; as=style
# Prefetch 响应头
Link: </next-page.js>; rel=prefetch; as=script
3. JavaScript 动态创建
// Preload 动态创建
const preloadLink = document.createElement('link');
preloadLink.rel = 'preload';
preloadLink.as = 'font';
preloadLink.href = 'font.woff2';
preloadLink.crossOrigin = 'anonymous';
document.head.appendChild(preloadLink);
// Prefetch 动态创建
const prefetchLink = document.createElement('link');
prefetchLink.rel = 'prefetch';
prefetchLink.as = 'script';
prefetchLink.href = 'next-page-bundle.js';
document.head.appendChild(prefetchLink);
三、关键参数说明
as 属性(必需):
- 指定资源类型:
script
,style
,image
,font
,fetch
,document
,audio
,video
- 浏览器根据类型设置优先级和缓存策略
- 指定资源类型:
crossorigin:
- 字体等 CORS 资源必须设置:
crossorigin="anonymous"
- 错误设置会导致重复加载
- 字体等 CORS 资源必须设置:
type(可选):
- MIME 类型提示:
type="font/woff2"
- 浏览器可拒绝不支持的类型
- MIME 类型提示:
imagesrcset & imagesizes:
- 响应式图片预加载专用
<link rel="preload" as="image" href="hero.jpg" imagesrcset="hero-400.jpg 400w, hero-800.jpg 800w" imagesizes="(max-width: 600px) 400px, 800px" />
- 响应式图片预加载专用
四、浏览器行为对比
行为 | Preload | Prefetch |
---|---|---|
优先级 | High/Very High | Lowest |
网络阻塞 | 可能阻塞渲染 | 完全非阻塞 |
缓存有效期 | 遵循资源 Cache-Control | 5 分钟(Chrome) |
重复加载 | 相同 URL 仅加载一次 | 相同 URL 仅加载一次 |
页面卸载时 | 继续加载 | 立即中止加载 |
资源未使用 | 控制台警告(Chrome) | 静默失效 |
五、最佳实践与陷阱
✅ 正确使用姿势
Preload 黄金法则:
<!-- 三步曲 --> <link rel="preload" href="font.woff2" as="font" crossorigin /> <link rel="preload" href="critical.css" as="style" onload="this.rel='stylesheet'" /> <noscript><link rel="stylesheet" href="critical.css" /></noscript>
Prefetch 智能触发:
// 用户悬停时预取 document.querySelector('.next-page').addEventListener( 'mouseenter', () => { const link = document.createElement('link'); link.rel = 'prefetch'; link.href = 'next-page.js'; document.head.appendChild(link); }, { once: true } );
⚠️ 常见陷阱
滥用 Preload:
<!-- 反模式:非关键资源占用带宽 --> <link rel="preload" href="social-icons.png" as="image" />
缺失 as 属性:
<!-- 错误:优先级降为Lowest --> <link rel="preload" href="important.js" />
字体未设 crossorigin:
<!-- 导致二次加载 --> <link rel="preload" href="font.woff2" as="font" />
六、性能影响实测
电商网站案例:
优化项 | LCP 改善 | FID 改善 | 收入提升 |
---|---|---|---|
关键 CSS Preload | -42% | -28% | +7.3% |
首图 Preload | -51% | - | +12.1% |
下一页 Prefetch | - | -65% | +9.2% |
数据来源:WebPageTest + Google Analytics 实测
七、面试高频问题
Preload 和 Prefetch 的优先级区别?
Preload 根据
as
类型设置优先级(字体=Highest),Prefetch 固定为 Lowest如何避免 Preload 资源浪费?
使用
onload
事件释放资源:const preload = document.createElement('link'); preload.rel = 'preload'; preload.as = 'script'; preload.href = 'app.js'; preload.onload = () => { const script = document.createElement('script'); script.src = 'app.js'; document.body.appendChild(script); preload.remove(); // 移除preload标签 };
Prefetch 的资源何时被使用?
导航到新页面时,浏览器直接从 disk cache 读取
Preload 字体为什么需要 crossorigin?
字体默认以 CORS 模式加载,preload 需匹配相同模式
如何检测 Preload/Prefetch 效果?
// 性能时间线检测 const entries = performance.getEntriesByType('resource'); entries.filter( (e) => e.initiatorType === 'link' && e.name.includes('preload') );
八、面试回答策略
概念分层:
"Preload 是当前页面的'急救包',用于关键路径资源;Prefetch 是下个页面的'预备粮',提升导航体验"
场景化举例:
"在电商详情页,我们 Preload 首屏商品图,Prefetch 用户可能点击的推荐商品数据"
技术深度:
"Preload 的优先级映射:
as=font
: Highestas=style
: Highestas=script
: Highas=image
: Low (非 LCP 图片)"
性能数据支撑:
"通过 Preload 关键 CSS,项目 LCP 从 4.2s→2.3s,Prefetch 使后续页面加载速度提升 300%"
错误处理经验:
"我们曾遇到 Preload 阻塞渲染的问题,最终通过
media
属性优化:<link rel="preload" href="print.css" as="style" media="print" /> ```"
💡 面试金句:
"Preload 和 Prefetch 是性能优化的精准手术刀——用对位置可提升关键指标,滥用则会导致资源争用。真正的艺术在于:在正确的时间,以正确的优先级,加载正确的资源。"