<link rel="preload">是最直接可靠的预加载方式,需指定as="image"和静态准确路径,Chrome 109+可加fetchpriority="high";new Image()适用于运行时条件预加载,须先绑定事件再赋值src;loading="lazy"等不是预加载。

用 <link rel="preload"> 是最直接、最可靠的方式,适用于你明确知道某张图会在首屏或交互初期立刻用到的场景。其他方式要么无效(比如误用 loading="lazy"),要么控制力弱、兼容性差(比如 CSS background 伪预加载)。
用 <link rel="preload"> 声明关键图
这是目前浏览器支持最好、语义最清晰、Lighthouse 能识别的预加载方式。它不渲染、不占布局,只把图片下进缓存。
-
as="image"必须写,缺了浏览器可能当普通 fetch 处理,失去图片专用缓存和解码策略 - 路径必须是静态且准确:相对路径基于 HTML 文件位置解析,比如 HTML 在
/user/profile.html,就别写./images/hero.jpg,改用/images/hero.jpg或绝对 URL -
fetchpriority="high"在 Chrome 109+ 有效,能抬高请求优先级;旧版忽略无副作用 - 不能在
href里写模板变量或 JS 表达式,比如"/assets/${name}.webp"会当字面量请求,大概率 404
示例:
<link rel="preload" as="image" href="/assets/logo.webp" fetchpriority="high"> <link rel="preload" as="image" href="/assets/banner.jpg">
用 new Image() 实现运行时条件预加载
当你需要根据用户行为、设备特性或状态决定是否加载时(比如 hover 后预载下一页缩略图、按 window.devicePixelRatio 加载 @2x 版本),Image 对象是唯一可控的选择。
立即学习“前端免费学习笔记(深入)”;
- 顺序不能错:先绑定
onload/onerror,再赋值src;否则缓存命中时事件同步触发,回调会被跳过 - 检查
img.complete:如果为true,说明已缓存,需立刻执行成功逻辑 - 避免密集
new Image():浏览器并发请求数通常只有 6~8 个,建议加队列或 Promise 控制(例如每次最多 4 个)
基础封装示例:
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"只影响解码时机,和下载无关 - CSS 的
background+-9999px位移方式虽能触发加载,但会随 HTML 一起阻塞解析,且无法感知成败,也不推荐用于关键图
真正容易被忽略的是路径解析规则和 as="image" 的强制性——写错一个斜杠或漏掉这个属性,<link rel="preload"> 就退化成普通 fetch,失去预加载意义。WebP 等现代格式还要额外考虑 fallback,但那是另一层问题了。



















