JS `Image Optimization`:响应式图片、WebP/AVIF 格式与懒加载

嘿,大家好!我是今天的主讲人,很高兴能和大家一起聊聊前端性能优化里一个非常重要的环节——图片优化。别害怕,这玩意儿其实没那么玄乎,咱们把它掰开了揉碎了,保证大家听完之后都能成为图片优化大师(至少是入门级)。

今天咱们主要聊三个方面:响应式图片、WebP/AVIF 格式以及懒加载。这三板斧下去,你的网站图片性能至少能提升一个档次!

第一板斧:响应式图片,让图片“随机应变”

想象一下,你有一个特别高清的图片,放在电脑上看那是真漂亮,细节满满。但是,当用户用手机访问你的网站时,这么大的图片不仅加载慢,还浪费流量,简直是“杀鸡用牛刀”。响应式图片就是为了解决这个问题而生的。

简单来说,响应式图片就是根据用户的设备(屏幕尺寸、分辨率等)来加载不同尺寸或者不同清晰度的图片。这样,在大屏幕上就能看到高清图,在小屏幕上就能加载小图,既保证了视觉效果,又节省了流量。

怎么实现呢?主要有两种方式:

1. <picture> 元素

<picture> 元素允许你为不同的屏幕尺寸、分辨率等条件指定不同的图片资源。它的结构大概是这样的:

<picture>
  <source media="(max-width: 600px)" srcset="small.jpg">
  <source media="(max-width: 1200px)" srcset="medium.jpg">
  <img src="large.jpg" alt="描述图片的文字">
</picture>
  • <picture>:最外层的容器,包裹所有图片资源。
  • <source>:定义一个图片资源,media 属性定义媒体查询条件,srcset 属性指定符合条件的图片 URL。
  • <img>:兜底图片,如果没有任何 <source> 匹配,就加载 <img> 里的图片。alt 属性是必须的,用于描述图片内容,对 SEO 和可访问性很重要。

例子:

假设我们有三张图片:small.jpg (600px 宽),medium.jpg (1200px 宽),large.jpg (原始尺寸)。

<picture>
  <source media="(max-width: 600px)" srcset="small.jpg">
  <source media="(max-width: 1200px)" srcset="medium.jpg">
  <img src="large.jpg" alt="一只可爱的猫咪">
</picture>

当屏幕宽度小于等于 600px 时,加载 small.jpg;当屏幕宽度小于等于 1200px 时,加载 medium.jpg;否则,加载 large.jpg

srcset 的进阶用法:像素密度(DPR)

除了根据屏幕宽度选择图片,我们还可以根据像素密度(DPR,Device Pixel Ratio)来选择图片。DPR 表示一个 CSS 像素对应多少个物理像素。比如,DPR 为 2 的屏幕,一个 CSS 像素对应 2×2=4 个物理像素。

srcset 可以使用 x 描述符来指定像素密度。

<picture>
  <source srcset="image.png 1x, image-2x.png 2x" type="image/png">
  <img src="image.png" alt="示例图片">
</picture>
  • image.png 1x:表示 DPR 为 1 的屏幕加载 image.png
  • image-2x.png 2x:表示 DPR 为 2 的屏幕加载 image-2x.png

sizes 属性

sizes 属性用于告诉浏览器,在不同的媒体查询条件下,图片显示的宽度。这个属性和 srcset 一起使用,可以帮助浏览器更准确地选择合适的图片。

<img
  srcset="image-320w.jpg 320w,
          image-480w.jpg 480w,
          image-800w.jpg 800w"
  sizes="(max-width: 320px) 280px,
         (max-width: 480px) 440px,
         800px"
  src="image-800w.jpg"
  alt="示例图片">
  • srcset:列出不同宽度的图片资源,并用 w 描述符表示宽度。
  • sizes:列出媒体查询条件和对应的图片显示宽度。
    • (max-width: 320px) 280px:当屏幕宽度小于等于 320px 时,图片显示宽度为 280px。
    • (max-width: 480px) 440px:当屏幕宽度小于等于 480px 时,图片显示宽度为 440px。
    • 800px:其他情况下,图片显示宽度为 800px。
  • src:兜底图片。

2. <img> 元素的 srcsetsizes 属性

除了 <picture> 元素,我们还可以直接在 <img> 元素上使用 srcsetsizes 属性来实现响应式图片。这种方式更简洁,适用于简单的场景。

<img
  srcset="small.jpg 600w, medium.jpg 1200w, large.jpg 2000w"
  sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 1000px"
  src="large.jpg"
  alt="一只可爱的猫咪">
  • srcset:指定不同宽度的图片资源,600w1200w2000w 分别表示图片的宽度。
  • sizes:指定在不同媒体查询条件下,图片显示的宽度。
    • (max-width: 600px) 100vw:当屏幕宽度小于等于 600px 时,图片显示宽度为屏幕宽度的 100%。
    • (max-width: 1200px) 50vw:当屏幕宽度小于等于 1200px 时,图片显示宽度为屏幕宽度的 50%。
    • 1000px:其他情况下,图片显示宽度为 1000px。
  • src:兜底图片。

总结一下:

特性 <picture> 元素 <img> 元素的 srcsetsizes 属性
结构 复杂,需要嵌套 <source><img> 元素。 简单,直接在 <img> 元素上使用属性。
适用场景 复杂场景,需要根据不同的媒体查询条件选择不同的图片格式(例如 WebP 和 JPEG)或者不同的图片内容。 简单场景,只需要根据屏幕尺寸选择不同大小的图片。
灵活性 非常灵活,可以完全控制图片的加载逻辑。 相对灵活,但不如 <picture> 元素。
兼容性 兼容性良好,主流浏览器都支持。 兼容性良好,主流浏览器都支持。

第二板斧:WebP/AVIF 格式,让图片“瘦身”

传统的 JPEG、PNG 格式虽然应用广泛,但是压缩效率相对较低。WebP 和 AVIF 格式是更现代的图片格式,它们可以在保证图片质量的前提下,大幅度减小图片体积,从而加快加载速度。

1. WebP

WebP 是 Google 开发的一种图片格式,它支持有损压缩和无损压缩,可以提供比 JPEG 和 PNG 更好的压缩效果。

  • 优势:
    • 压缩率高:相同质量下,WebP 通常比 JPEG 小 25%-34%。
    • 支持透明度:支持 Alpha 透明度,可以替代 PNG。
    • 支持动画:支持动画,可以替代 GIF。
  • 劣势:
    • 兼容性:虽然主流浏览器都支持 WebP,但是一些老旧浏览器可能不支持。

2. AVIF

AVIF (AV1 Image File Format) 是一种基于 AV1 视频编码的图片格式。AV1 是一种开源、免版税的视频编码格式,AVIF 继承了 AV1 的优点,可以提供比 WebP 更高的压缩效率。

  • 优势:
    • 压缩率极高:相同质量下,AVIF 通常比 WebP 小 20%-30%。
    • 支持 HDR:支持高动态范围(HDR)图像。
  • 劣势:
    • 兼容性:AVIF 的兼容性不如 WebP,一些老旧浏览器可能不支持。
    • 编码复杂度高:AVIF 的编码复杂度较高,编码速度较慢。

如何使用 WebP/AVIF?

  1. 图片转换: 可以使用专业的图片处理软件(如 Photoshop)或者在线工具将图片转换为 WebP/AVIF 格式。
  2. 服务器配置: 确保你的服务器支持 WebP/AVIF 格式。
  3. 使用 <picture> 元素: 使用 <picture> 元素,为支持 WebP/AVIF 的浏览器提供 WebP/AVIF 图片,为不支持的浏览器提供 JPEG/PNG 图片。
<picture>
  <source srcset="image.avif" type="image/avif">
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="示例图片">
</picture>
  • 浏览器会按照 <source> 元素的顺序,选择第一个支持的图片格式。
  • 如果浏览器支持 AVIF,就加载 image.avif;如果支持 WebP,就加载 image.webp;如果都不支持,就加载 image.jpg

关于兼容性:

浏览器 WebP 支持 AVIF 支持
Chrome Yes Yes
Firefox Yes Yes
Safari Yes Yes
Edge Yes Yes
Opera Yes Yes
IE No No

第三板斧:懒加载,让图片“按需加载”

想象一下,你的网站有很多图片,但是用户第一次访问时,只需要看到首屏的图片。如果一次性加载所有图片,会浪费大量的带宽和资源,导致页面加载速度变慢。懒加载就是为了解决这个问题而生的。

懒加载是指延迟加载页面上的图片,只有当图片出现在用户的可视区域内时才加载。这样可以减少初始加载时间,提高用户体验。

如何实现懒加载?

主要有两种方式:

1. Intersection Observer API

Intersection Observer API 是一种高效的监听元素是否进入可视区域的 API。它可以异步地监听目标元素与祖先元素或 viewport 的交叉状态。

const images = document.querySelectorAll('img[data-src]');

const observer = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target;
      img.src = img.dataset.src;
      img.removeAttribute('data-src');
      observer.unobserve(img);
    }
  });
});

images.forEach(img => {
  observer.observe(img);
});
  • document.querySelectorAll('img[data-src]'):选择所有带有 data-src 属性的 <img> 元素。data-src 属性用于存储图片的真实 URL。
  • IntersectionObserver:创建一个 Intersection Observer 实例。
    • entries:一个包含 IntersectionObserverEntry 对象的数组,每个对象描述了一个被观察元素与根元素的交叉状态。
    • observer:IntersectionObserver 实例本身。
  • entry.isIntersecting:判断元素是否进入可视区域。
  • img.src = img.dataset.src:将 data-src 属性的值赋给 src 属性,开始加载图片。
  • img.removeAttribute('data-src'):移除 data-src 属性,防止重复加载。
  • observer.unobserve(img):停止观察该元素。
  • observer.observe(img):开始观察每个 <img> 元素。

HTML 结构:

<img data-src="image.jpg" alt="示例图片">

2. loading 属性

HTML 提供了一个 loading 属性,可以用于实现图片的懒加载。这个属性有三个值:

  • lazy:延迟加载图片,直到图片接近可视区域。
  • eager:立即加载图片,无论图片是否在可视区域内。
  • auto:由浏览器决定是否懒加载图片。
<img src="image.jpg" alt="示例图片" loading="lazy">

兼容性:

loading 属性的兼容性良好,主流浏览器都支持。

懒加载的注意事项:

  • 首屏图片: 不要对首屏图片使用懒加载,否则会影响首屏加载速度。
  • 占位符: 在图片加载之前,可以使用占位符来避免页面布局抖动。
  • SEO: 确保搜索引擎能够抓取到懒加载的图片,可以使用 noscript 标签提供图片的备用链接。

总结:

今天我们聊了图片优化的三个方面:响应式图片、WebP/AVIF 格式以及懒加载。

  • 响应式图片: 根据用户的设备选择合适的图片尺寸,节省流量,提高加载速度。可以使用 <picture> 元素或者 <img> 元素的 srcsetsizes 属性来实现。
  • WebP/AVIF 格式: 使用更高效的图片格式,减小图片体积,加快加载速度。
  • 懒加载: 延迟加载可视区域外的图片,减少初始加载时间,提高用户体验。可以使用 Intersection Observer API 或者 loading 属性来实现。

一些额外的建议:

  • 图片压缩: 在上传图片之前,可以使用专业的图片压缩工具(如 TinyPNG、ImageOptim)来减小图片体积。
  • CDN: 使用 CDN (Content Delivery Network) 可以将图片分发到全球各地的服务器上,加快用户的访问速度。
  • HTTP 缓存: 合理设置 HTTP 缓存策略,可以减少重复加载图片的次数。

希望今天的讲座对大家有所帮助!记住,图片优化是一个持续的过程,需要不断地学习和实践。祝大家都能成为图片优化大师!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注