JavaScript 中如何通过图片懒加载与 WebP/AVIF 优化资源加载

拾光
拾光
发布时间:2026-08-24| 161人浏览过
原创

前言

前端页面里,图片往往是最容易拖慢首屏的资源,但很多项目要么只做压缩,要么把所有图片一股脑懒加载,结果关键指标反而不稳。本文把图片优化拆成“加载时机”和“资源格式”两部分,结合首屏图、内容图和 SPA 场景,梳理一套更容易直接落地的判断方法。

图片资源往往占据页面传输体积的大头,真正影响体验的也常常不是脚本本身,而是首屏关键图是否及时到达、非首屏图片是否过早请求。把图片懒加载和 WebP、AVIF 这两类手段配合起来看,思路会更清晰:前者解决“不该现在加载的别急着加载”,后者解决“必须加载的尽量更小”。

这篇文章按实际落地顺序来拆解:先看浏览器原生能力能解决多少,再看什么时候需要用 IntersectionObserver 精细控制,最后补上现代图片格式与首屏策略。读完后,你可以判断哪些图片该懒加载、哪些不能动,以及格式升级该怎么做才不影响兼容性。

原生懒加载:先用最低成本拿到收益

如果项目面向的是现代浏览器,图片懒加载最直接的做法就是使用 loading 属性。当前主流浏览器已经提供原生支持:Chrome 76+、Edge 79+、Firefox 75+、Safari 15.4+。

原生懒加载与关键图例外规则示意图
哪些图片适合直接懒加载把可懒加载图片与必须立即加载的首屏关键图分开处理,通常是图片优化最先见效的一步。

对非首屏图片,可以直接在 <img> 上添加 loading="lazy"。浏览器通常会在图片接近视口前大约 1250px 时发起请求,具体提前量会随设备和环境调整。这种方式的优点是改动很小,不需要额外脚本,也能快速减少首屏阶段的非必要请求。

但这里有一个判断标准不能错:首屏关键图不要懒加载。对于首页主视觉、商品主图、文章头图这类明显会参与首屏展示、甚至可能成为 LCP 候选的图片,要么不写这个属性,要么显式设置为 loading="eager",确保浏览器立即处理。

此外,原生懒加载不仅适用于 <img>,对 <iframe> 同样生效。不过如果图片是通过 CSS background-image 挂载的,仅靠这个属性并不能延迟加载,通常还需要结合 JavaScript,在合适时机再动态写入 background-image。

还有一个常被忽略的配套动作,是为图片提前声明尺寸。无论是直接写 width、height,还是通过 CSS 的 aspect-ratio 预留比例空间,目的都一样:避免图片加载完成后把原有布局顶开,造成 CLS。

需要更细控制时,用 IntersectionObserver

原生懒加载已经覆盖了大量场景,但一旦需求变复杂,IntersectionObserver 会更稳。典型情况包括:需要兼容旧浏览器、想把触发距离从默认策略改成“提前 200px 加载”、或者要接入占位图、错误回退、重试逻辑时。

一个常见实现方式是把真实图片地址先放进 data-src,而 src 使用一个极小的占位图,例如 1×1 透明 base64:

data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==

这样页面初始渲染时不会立刻请求真实资源,等观察器确认元素即将进入视口,再把 data-src 替换到 src 上。

实现上要注意复用 Observer。更合理的写法是创建一个全局或模块级的单个 Observer 实例,用它去监听一组图片,而不是每个元素都新建一个 observer。后者虽然也能工作,但会带来额外的实例开销,页面图片一多就不划算。

如果你希望用户滚动到图片位置时几乎感受不到等待,可以通过 rootMargin: "200px" 之类的设置,让图片在进入可视区之前就开始加载。这个值并没有统一标准,列表流内容、瀑布流和长文详情页的最佳距离可能都不一样,通常需要结合网络条件和内容密度来调。

当图片成功加载后,记得执行 unobserve(el),避免后续重复触发同一逻辑。如果请求失败,也不要让页面直接显示破图,应该在 error 事件里回退到备用图,必要时再叠加重试策略。

格式升级:把必须加载的图片继续压小

懒加载解决的是请求时机,格式升级解决的是资源体积。对页面性能来说,这两件事应该同时做。

AVIF、WebP 与降级加载链路示意图
现代格式该怎么选和怎么降级格式升级解决的是体积问题,和懒加载配合后,才能同时压缩请求数量与单次传输成本。

在现代格式里,AVIF 和 WebP 是最常用的两条路线。对于首屏大图、LCP 图像这类体积大、影响关键渲染路径的资源,AVIF 优先级更高。按照原文给出的经验,同等质量下它通常比 JPEG 小 50%+,同时支持更高压缩率和更好的色深表现。

如果场景更看重通用性、编码速度和兼容范围,WebP 往往更适合作为主力格式。它在浏览器侧支持更广,生成速度也更快,体积通常仍比 JPEG 或 PNG 小 25–35%。这使它非常适合大多数内容图、通用插图和图标资源。

实际部署时,最稳妥的方式不是只押一种格式,而是通过 <picture> 和 <source> 做渐进式降级,让浏览器按能力选择:

<picture>
  <source srcset="hero.avif" type="image/avif" />
  <source srcset="hero.webp" type="image/webp" />
  <img src="hero.jpg" alt="..." />
</picture>

这套链路的核心顺序就是 image/avif → image/webp → image/jpeg。支持 AVIF 的浏览器拿到最小资源,不支持的再自动降级到 WebP 或 JPEG,兼容性和性能可以一起兼顾。

如果项目后面还有服务端或 CDN,可以进一步利用内容协商。也就是根据请求头里的 Accept 返回对应格式,并为静态资源设置长期强缓存:

Cache-Control: public, max-age=31536000, immutable

这样做能减少重复传输,尤其适合经过构建指纹处理、内容变更即文件名变化的图片资源。

首屏图、响应式图片和 SPA 场景的细节处理

图片优化容易做出“看起来做了很多,实际收益打折”的结果,问题通常就出在这些细节上。

首先,首屏关键图除了不要懒加载,还应补上更明确的优先级提示。可以加上 fetchpriority="high" 和 decoding="async",前者告诉浏览器这是高优先级资源,后者帮助图片解码更高效地融入渲染流程。

其次,响应式图片不能只做一半。如果页面使用了不同尺寸图片源,就要同步配置 srcset 和 sizes。否则即便懒加载生效,浏览器仍可能因为尺寸判断不准确而先拉取低清版本,影响最终显示质量。

对单页应用来说,图片优化还要考虑“页面不是一次性生成”的问题。比如路由切换、新列表追加、组件异步挂载之后,新的图片元素并不会自动进入既有监听流程,这时需要在组件挂载后重新执行 observer.observe(),确保新插入节点也能按预期懒加载。

最后,有些图片从语义上就不该进入懒加载名单。轮播首帧、商品主图、Banner 主视觉这类资源,往往天然就是 LCP 候选。如果为了“全站统一策略”把它们也懒加载,反而会拖慢首屏关键指标,这类图应始终优先请求。

怎么判断一张图该不该懒加载

如果要把这套方法真正落地,可以用一个简单标准来判断:先区分“首屏关键图”和“滚动后才会看到的内容图”。前者关注尽快展示,优先考虑 loading="eager"、fetchpriority="high"、AVIF/WebP 和尺寸声明;后者关注减少初始请求,适合使用 loading="lazy" 或 IntersectionObserver 延迟加载。

再往下一层看,懒加载和格式升级不是替代关系,而是叠加关系。非首屏图片可以懒加载,也应该尽量使用 WebP 或 AVIF;首屏关键图虽然不能懒加载,但同样值得升级格式、配合缓存和响应式资源策略。只有把“时机”和“体积”同时处理好,LCP、CLS 和首屏加载时间才会稳定改善。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。