最直接的浏览器原生图片预加载方式是<link rel="preload" as="image">,必须置于<head>中且每张图单独声明,避免混淆prefetch或误用loading="eager"。

用 link rel="preload" 预加载多张图片最直接
浏览器原生支持的预加载方式,不执行 JS 也能提前触发下载,且优先级高、可控性强。关键不是“怎么写多个”,而是“怎么写才不被忽略”。
常见错误是把 link 写在 <body> 里——它必须放在 <head> 中,否则多数浏览器会无视;还有人用 rel="prefetch" 混淆用途,那只是低优先级提示,不适合首屏关键图。
-
<link rel="preload" as="image" href="/hero.jpg">必须带as="image",否则浏览器不会按图片解码逻辑处理 - 每张图单独写一条
link,不能合并路径或用通配符 - 如果图片带响应式
srcset,preload只能指定单个 URL,建议预加载你确定会在当前视口用到的那张(比如桌面端加载hero-1200w.jpg) - 避免预加载超过 3–4 张,过多会挤占关键资源带宽,尤其对弱网用户反而拖慢首屏
JS 动态预加载适合条件触发场景
当图片是否预加载取决于运行时逻辑(比如用户 hover 到某个模块、或进入某页签),就得用 JS 主动创建 Image 实例。这不是“模拟加载”,而是真实发起请求并缓存到内存/磁盘。
注意:仅 new Image() 不够,必须赋值 src 才触发下载;但别忘了加 onload 和 onerror 监听,否则失败了你完全不知道。
立即学习“前端免费学习笔记(深入)”;
- 写法:
const img = new Image(); img.onload = () => console.log('预加载完成'); img.onerror = () => console.error('预加载失败'); img.src = '/banner.webp'; - 批量操作建议用
Promise.all包裹,方便统一控制时机:Promise.all(images.map(src => preloadImage(src))) - 不要在
DOMContentLoaded之前就执行大量预加载,可能和主文档解析争抢 HTTP/1.1 连接数(HTTP/2+ 影响小些)
警惕 loading="eager" 不是预加载
很多人看到 <img loading="eager"> 就以为是预加载,其实它只影响浏览器的懒加载策略开关,和资源发起时机无关——它仍要等到 HTML 解析到该标签才开始请求,无法提前。
典型误用场景:把轮播图第二张图设成 loading="eager",指望它比第一张更早加载。结果是两张图几乎同时发起请求,毫无提前量。
-
loading="eager"等价于不写loading属性,默认行为 - 真正想“提前”,必须靠
link preload或 JSnew Image() - 如果图片本身在首屏内,
loading="eager"没实际意义;如果在视口外,强行设它反而增加首屏渲染压力
WebP/AVIF 图片要注意 MIME 类型和 CDN 缓存
用 link preload 加载 WebP 或 AVIF 时,部分老旧 CDN 或代理会因不识别 as="image" 对应的 MIME 类型,返回 404 或降级成 JPEG。这不是代码写错了,是基础设施没跟上。
- 检查响应头:
Content-Type必须是image/webp或image/avif,否则浏览器可能拒绝解码 - 本地测试正常 ≠ 上线正常,务必在真实 CDN 环境下用 Network 面板看实际返回状态和类型
- 若 CDN 不支持 AVIF,可 fallback 到 WebP,但预加载只能选一种格式——别试图用
picture+preload组合,preload不理解source的媒体查询逻辑



















