预加载图片不能提升页面实际加载速度,但能提升用户感知速度;需在 domcontentloaded 后立即执行,检查 img.complete 状态,绑定 onload/onerror,控制并发批次,并用 devtools 验证缓存命中。

预加载图片本身不会让页面“变快”,但它能让用户感知到更快——关键在于让图片在需要时已存在于缓存中,避免白屏、闪烁或突然拉伸。这需要选对时机、方式和校验机制,否则容易白忙一场。
用 new Image() 预加载时,必须检查 complete 属性
很多人直接设置 img.src = url 就以为完事了,但浏览器可能早已从缓存返回该图,onload 根本不触发,导致后续逻辑卡住。
-
img.complete为true表示图片已缓存就绪,可立即使用尺寸、触发回调 - 只有
img.complete === false时,才需监听onload或onerror - 别忘了同时绑定
onerror:404 或跨域失败时,onload不会调用,不处理就会静默失败
不要在 window.onload 里才开始预加载
等整个页面(含 CSS、JS、字体、第三方脚本)都加载完再预加载图片,已经错过最佳时机——用户可能已经滚动到图片位置,甚至点开了新页面。
- 推荐在
DOMContentLoaded后立即启动预加载,此时 DOM 已就绪,但图片等资源尚未阻塞 - 更激进的做法:在首屏关键图片 URL 确定后(比如从 JSON API 获取),立刻发起预加载,不等任何事件
- 避免用
setTimeout(..., 0)模拟“异步”,它不可靠,且延迟不可控
CSS background 预加载只适用于静态路径,且有隐藏代价
用 .preload-1 { background: url(x.jpg) no-repeat -9999px -9999px; } 看似简单,但实际会影响页面初始加载性能。
- 这些图片会和 HTML/CSS 一起被浏览器并行请求,挤占首屏关键资源带宽
- 路径必须完全一致(含查询参数),
logo.png?v=2和logo.png?v=3在缓存中是两个不同资源 - 无法获知是否加载成功,也无法做降级(比如 fallback 到占位图)
- 现代项目中,建议仅用于极少量、确定不变的 UI 图标类资源
批量预加载要控制并发,避免打爆连接池
一次性 new 50 个 Image 对象,在 Chrome 下可能触发 6 个并发连接限制,后面图片排队等待,反而拖慢整体完成时间。
- 建议按每批 4–6 张分组,上一批
onload全部触发后再加载下一批 - 对超大图或弱网场景,可结合
fetch(url, { mode: 'no-cors' })+createObjectURL,规避部分跨域限制(但注意内存释放) - 服务端支持的话,优先用
<link rel="preload" as="image" href="...">,由浏览器原生调度,更可靠
最容易被忽略的一点:预加载不是“扔出去就完事”。你得确认它真进了缓存——用 DevTools 的 Network 面板过滤 Img,看重复请求是否显示 from cache 或 memory cache,而不是又走了一次网络。没验证过的预加载,和没写一样。











