应分批限流预加载图片,每批4张并用promise.allsettled处理,仅预载可见及相邻项(最多3张),webp需在head中静态声明双link且路径须与最终img src完全一致。

用 Promise.allSettled + 队列控制并发数
浏览器对同一域名的并发图片请求数有硬限制(通常 6~8 个),直接 new Image() 循环 100 次,大部分请求会排队等待,甚至触发超时或被降级。必须分批、限流。
核心是把海量图片 URL 切成小批次(比如每批 4 张),用 Promise.allSettled 等待整批完成,再处理下一批。不推荐 Promise.all,因为单张失败会导致整批中断。
- 先封装一个带错误捕获的预加载函数:
preloadImage(url),内部创建Image、绑定onload/onerror、检查img.complete - 把所有 URL 分组:例如
chunkArray(urls, 4),返回二维数组 - 用
for...of逐批执行,避免一次性压入太多 Promise 导致内存激增 - 批次之间可加
await new Promise(r => setTimeout(r, 50))微延迟,缓解主线程压力
fetch() + createObjectURL() 不适合纯预加载
有人想用 fetch(url).then(r => r.blob()).then(blob => URL.createObjectURL(blob)) 来“更可控”地预加载,这反而绕远路:
-
fetch不走浏览器图片缓存机制,后续<img src="...">仍会重新发起 HTTP 请求 -
createObjectURL生成的 URL 是临时的,必须手动调用URL.revokeObjectURL(),否则内存泄漏 - 没有自动适配
srcset、sizes或设备像素比的能力,而Image对象能天然复用这些逻辑
除非你要做图片校验或格式转换,否则别碰这条路。
轮播图/画廊类场景:只预载「可见+相邻」范围
海量图片往往出现在轮播图、商品画廊、相册页等场景。这时根本不需要全量预加载——用户几乎不会一口气翻完 200 张图。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
合理策略是:只预加载当前项、前一项、后一项(共最多 3 张)。切换时动态更新:
- 监听轮播切换事件(如
slideChange),拿到目标索引targetIndex - 计算需预加载的索引集合:
[targetIndex - 1, targetIndex, targetIndex + 1],过滤越界 - 对每个索引查出对应 URL,丢进上面的队列函数里 —— 每次只预载 3 张,响应快、无冗余
- 避免重复:用
Set缓存已成功预加载的 URL,防止切换来回时反复触发
WebP + fallback 的预加载必须静态声明
如果你用 <link rel="preload" as="image"> 预加载 WebP 图,但还要兼容不支持 WebP 的旧浏览器(如 Safari 13 以下),不能靠 JS 动态 fallback。
原因:<link rel="preload"> 是 HTML 解析阶段就触发的,它不执行 JS,也不识别 picture 里的 source 切换逻辑。
- 正确做法:在
中同时写两条<link>,分别指向 WebP 和 JPG 版本,并加fetchpriority="high"给 WebP - 实际渲染时用
<picture></picture>+<source type="image/webp"></source>+<img>fallback,让浏览器自己选 - 错误写法:
href="./images/photo.webp?fallback=./photo.jpg"—— 参数会被当字面量,导致 404
真正容易被忽略的是:预加载的资源路径必须和最终 <img> 渲染时的 src 完全一致(含协议、域名、大小写、查询参数),否则浏览器不会命中缓存,等于白干。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










