link rel="preload" 是最直接可靠的预加载方式,适用于明确知道图片将在详情页首屏或交互初期立即使用的场景;必须写 as="image",路径需静态准确,fetchpriority="high" 仅 Chrome 109+ 有效;new Image() 适合按需预加载非首屏图,需先绑定事件再赋值 src,并确保 URL 完全一致;loading="lazy" 和 display: none 不是预加载手段。

link rel="preload" 是最直接可靠的预加载方式,适用于你明确知道某张图会在详情页首屏或交互初期立刻用到的场景。其他方式要么无效(比如误用 loading="lazy"),要么控制力弱、兼容性差(比如 CSS background 伪预加载)。
用 link rel="preload" 预加载详情页核心图
这是目前浏览器支持最好、语义最清晰、Lighthouse 能识别的预加载方式。它不渲染、不占布局,只把图片下进缓存。
-
as="image"必须写,缺了浏览器可能当普通fetch处理,失去图片专用缓存和解码策略 - 路径必须是静态且准确:相对路径基于 HTML 文件位置解析,比如 HTML 在
/product/detail.html,就别写./images/main.jpg,改用/images/main.jpg或绝对 URL -
fetchpriority="high"在 Chrome 109+ 有效,能抬高请求优先级;旧版忽略无副作用 - 不能在
href里写模板变量或 JS 表达式,比如"/assets/${id}.webp"会当字面量请求,大概率 404
示例:
<head> <link rel="preload" as="image" href="/images/detail-main.webp" fetchpriority="high"> <link rel="preload" as="image" href="/images/detail-zoom.jpg"> </head>
用 new Image() 预加载详情页非首屏图(如缩略图、切换图)
当你需要根据用户行为决定是否加载时(比如点击“查看更多规格”后预载参数图,或滑动轮播前预载下一张),Image 对象是唯一可控的选择。
- 顺序不能错:先绑定
onload/onerror,再赋值src;否则缓存命中时事件同步触发,回调会被跳过 - 检查
img.complete:如果为true,说明已缓存,需立刻执行成功逻辑 - 避免密集
new Image():浏览器并发请求数通常只有 6~8 个,建议加队列或 Promise 控制(例如每次最多 4 个) - URL 必须完全一致:带查询参数(如
?v=20260930)的图,预加载和最终展示要用同一串 URL,否则缓存不命中
基础封装示例:
立即学习“前端免费学习笔记(深入)”;
const preloadImage = (url) => {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = () => reject(new Error(`Failed to load ${url}`));
img.src = url;
});
};
别把 loading="lazy" 或 display: none 当预加载用
这是最常见的误解。loading="lazy" 是推迟加载,不是提前加载。哪怕你给详情页首屏 <img> 显式加上它,Chrome 仍可能等到滚动前 500px 才发请求——完全违背预加载目标。
-
loading="eager"是默认行为,显式写出来也没错,但它只是“不懒”,不等于“提前” -
decoding="async"只影响解码时机(避免主线程卡顿),和下载时机无关 - 用
display: none包裹<img src="...">不可靠:它仍会触发初始加载,但无法监听状态,且可能干扰 LCP 计算
src 值**逐字节一致**,包括大小写、斜杠方向、查询参数。哪怕多一个空格或少一个 v=,浏览器就当全新资源处理,缓存形同虚设。



















