还在使用传统图片懒加载?

1,871 阅读3分钟

概述

图片懒加载是每一个前端绕不过的话题,在用户访问页面时,如果一次性加载所有图片会极大地影响用户体验。图片懒加载就是让浏览器只请求出现在可视区域中的图片。 传统图片懒加载方式有两种:

  • 监听 scroll 事件
  • IntersectionObserver API

第一种方式通过监听 scroll 事件判断图片是否出现在可视区域中,然后替换 src 属性。虽然这种方式的兼容性较好,但是 scroll 事件运行在主线程并且触发频繁,需要再写一个节流函数,非常不优雅。

第二种方式使用 IntersectionObserver API 监听页面元素的可见性,是目前最为推荐的一种方式。IntersectionObserver 更方便使用并且具有更好的可读性, 我们只需要考虑编写元素可见时需要执行的代码即可,主流浏览器也已经基本支持。

浏览器级别的懒加载

既然有了 IntersectionObserver 为什么还需要浏览器级别的懒加载支持,Chrome 团队给出的原因有两个:

  1. 不再需要引入外部工具或者库
  2. 浏览器禁止 JavaScript 也能正常工作

但是第二点 MDN 给出不同的意见:

仅在启用 JavaScript 时才会延迟加载。这是一种反跟踪的措施,因为,如果用户代理在禁用脚本的情况下支持延迟加载,网站仍然跨源通过在图像中策略性地放置图像来跟踪用户在整个会话期间的大致滚动位置,这样服务器可以跟踪请求了多少图像以及请求在何时发起。

经过实际测试,在停用 javascript 时不会开启懒加载。

使用方法

使用方法非常简单,只需要在 img 标签中添加一个 loading 属性即可。

<img src="image.png" loading="lazy" alt="…" width="200" height="200" />

loading 的属性值有两个:

  • lazy: 图片懒加载
  • eager: 图片正常加载

注意:使用 eager 的图片相比不使用 loading 属性的 img 标签并不会获得更高的加载优先级,所以正常加载的图片无需添加此属性。

效果

Chrome

为了让图片在进入视口时最大限度地加载完成,使用 lazy 属性的图片会在到达它附近的一个位置时就开始请求,chrome 中的请求过程如下:

可以看到在首次加载时请求了 5 张图片,下拉过程中到对应图片的距离到达一个阈值时就已经开始请求。

页面在刷新时会记住刷新前的位置,浏览器也很智能地请求这个位置附近阈值范围内的图片:

另一个重要的特性是浏览器会根据网络条件改变阈值范围,网速越慢,阈值越高。在高速 3G 条件下,chrome 首次加载了 7 张图片:

On fast connections (4G), we reduced Chrome's distance-from-viewport thresholds from 3000px to 1250px and on slower connections (3G or lower), changed the threshold from 4000px to 2500px.

根据 chrome 开发者的说法,在 4G 条件下阈值大小为 1250px,而在 3G 或者更低时这个值为 2500px

注意

  1. 各个浏览器厂商对阈值大小有不同的实现并可能会在未来更改。在测试中 Safari 和 Firefox 的阈值都比 chrome 要小,而且没有考虑到不同的网络条件。
  2. 阈值大小是硬编码的,开发者目前不能自定义。

Firefox

Safari

兼容性

本文测试平台:

chrome 109.0.5414.119(正式版本) (arm64)

firefox 109.0(64 位)

safari 16.3 (18614.4.6.1.5)

参考资料

web.dev/browser-lev…