动态图片预加载只能用 new image():先绑定 onload/onerror,再赋值 src;需检查 img.complete 判断缓存命中,用 promise 队列控制并发(如最多3个),webp 需 fallback 探测或 promise.race 降级,其他方式均不可靠。

用 link rel="preload" 无法预加载动态图片
因为 link rel="preload" 只接受静态 href 值,浏览器在 HTML 解析阶段就执行它,不支持模板变量、JS 表达式或运行时拼接路径。哪怕你写成 href="/images/${id}.webp",浏览器也会字面量请求这个字符串,结果是 404。
常见错误包括:在 Vue/React 模板里直接塞 link 标签、用 document.write 注入、或试图在 DOMContentLoaded 后动态创建 link —— 这些都无效,preload 必须在初始 HTML 中且位于 内,晚于首屏解析的插入不会触发预加载行为。
new Image() 是唯一可行的动态图片预加载方式
必须在 JS 运行时构造 Image 实例,并赋值真实 URL。关键点不是“创建”,而是“何时赋值 src”和“如何确认状态”:
- 先绑定
onload和onerror,再赋值src;否则缓存命中时事件同步触发,回调可能丢失 - 赋值后立刻检查
img.complete === true,为true表示已缓存,应立即执行成功逻辑 - 避免在循环中密集
new Image(),浏览器并发限制通常为 6–8 个,建议加 Promise 队列控制(例如每次最多 3 个) - 不要把
img挂到全局或长期闭包里,加载完可设img.src = ''辅助 GC
基础封装示例:
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;
});
};
// 使用
preloadImage('/assets/photo-' + userId + '@2x.webp')
.then(img => console.log('预加载完成'))
.catch(err => console.error(err));
WebP 动态预加载必须带 fallback
如果服务端按 Accept 头返回 WebP,但你想在 JS 里动态决定加载 WebP 还是 JPG,不能只写一个 src——用户网络或浏览器不支持 WebP 时会失败。
正确做法是:先探测支持性(document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') > -1),再选路径;或直接用 Promise.race 并行加载 WebP 和 JPG,取先成功的那个:
const loadWithFallback = (webpUrl, jpgUrl) => {
return Promise.race([
preloadImage(webpUrl).then(img => ({ img, format: 'webp' })),
preloadImage(jpgUrl).then(img => ({ img, format: 'jpg' }))
]);
};
注意:这种方式会多发一个请求,但能保证降级可用;别指望靠 picture + source 实现预加载,它只控制最终渲染,不触发提前下载。
别碰 loading="lazy" 或 display: none 伪方案
这两个和预加载完全无关:loading="lazy" 是推迟加载,Chrome 可能延迟到滚动前 500px 才发请求;display: none 的 img 标签仍按默认 eager 策略加载,但时机不可控,且占 DOM、影响 Lighthouse 评分。
更隐蔽的坑是:用 CSS background-image 配合 visibility: hidden 元素来“骗”浏览器加载——它确实会触发下载,但无法监听成功/失败,无法控制并发,且资源优先级远低于 preload 或 Image 对象,不推荐用于关键路径。
动态场景下,真正可控的只有 JS 主动发起的 Image 请求;所有“看起来像预加载”的其他手段,要么无效,要么不可靠,要么埋了监控和降级的雷。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











