图片加载快慢关键在「何时请求」和「请求哪张图」,而非单纯压缩体积;首屏图须preload并禁用loading="lazy",非首屏图才可安全启用该属性,且必须设置width/height防布局抖动。

图片加载快不快,不取决于你压了多少KB,而在于浏览器「什么时候发起请求」和「请求哪张图」。首屏大图没出来,页面就卡着;非可视区图片却抢带宽,用户还没滑到就下完了——这才是真瓶颈。
loading="lazy" 怎么用才不翻车
这是最轻量、原生支持的懒加载方案,但错用会直接拖垮首屏体验。
- 只对距首屏较远的
<img>加loading="lazy",比如列表页第 3 屏之后的图 - 首屏关键图(Banner、Logo、头像)必须禁用该属性,否则 Chrome 可能跳过加载或延迟渲染
-
loading="lazy"不影响srcset或<picture>的资源选择逻辑,它只是推迟触发时机 - 检测兼容性:
if ('loading' in HTMLImageElement.prototype),不支持时再降级用 IntersectionObserver
首屏图片怎么确保秒出
靠等 DOM 解析完再发请求?不行。浏览器解析到 <img src="hero.jpg"> 才开始下载,如果这张图是 1.2MB WebP,CDN 响应慢 300ms,首屏就白屏等着。
- 在
<head>中加<link rel="preload" as="image" href="hero.webp">,强制提前发起请求 -
href必须是最终加载的真实 URL(不能是占位符),且优先用.webp或.avif - 别乱 preload:它会抢占主文档和 CSS 的带宽,只对真正影响 LCP 的 1–2 张图用
- 可叠加
fetchpriority="high"(Chrome 107+),进一步提升调度优先级
srcset + sizes 怎么配才不浪费带宽
手机用户加载 2400px 桌面图?不是 CDN 没配好,是你没告诉浏览器“这图该在哪种条件下加载哪张”。
立即学习“前端免费学习笔记(深入)”;
- 用
srcset提供多尺寸资源:srcset="hero-400w.webp 400w, hero-800w.webp 800w, hero-1200w.webp 1200w" - 用
sizes告诉浏览器当前视口下该选哪个宽度:sizes="(max-width: 600px) 400px, (max-width: 1024px) 800px, 1200px" - 避免只靠 CSS 缩放:
<img style="width:100%">不会减少下载体积,浏览器仍拉原始大图 - 所有
<img>必须设width和height,否则加载时布局抖动(CLS)
自定义懒加载为什么一写就卡
用 IntersectionObserver 是为了兼容老浏览器或加占位图/错误回退,但写错容易重排、内存泄漏、甚至主线程卡死。
- 初始
<img src="placeholder.svg" width="300" height="200">,必须设宽高防抖动 - Observer 回调里只做两件事:
el.src = el.dataset.src,然后observer.unobserve(el) - 别在回调里塞 DOM 操作、AJAX 请求或重绘逻辑
- 监听前先过滤掉已在视口内的元素,否则刚进页面就批量触发,失去“懒”的意义
最容易被忽略的是:width/height 属性和 fetchpriority 的组合使用。很多项目加了 loading="lazy" 就以为万事大吉,结果首屏图没设尺寸导致布局抖动,LCP 还是超 4s——性能优化从来不是单点动作,而是加载时机、资源选择、渲染控制三者的协同。



















