现代图片性能优化: 懒加载及异步图像解码方案

图片的懒加载

懒加载是一种网页性能优化的常见方式,它能极大的提升用户体验。到今天,现在一张图片超过几 M 已经是常见事了。如果每次进入页面都需要请求页面上的所有的图片资源,会较大的影响用户体验,对用户的带宽也是一种极大的损耗。

所以,图片懒加载的意义即是,当页面未滚动到相应区域,该区域内的图片资源(网络请求)不会被加载。反之,当页面滚动到相应区域,相关图片资源的请求才会被发起。

在过去,我们通常都是使用 JavaScript 方案进行图片的懒加载。而今天,我们在图片的懒加载实现上,有了更多不一样的选择。

使用 content-visibility: auto 实现图片内容的延迟渲染

一个相对较为冷门的属性 – content-visibility

content-visibility:属性控制一个元素是否渲染其内容,它允许用户代理(浏览器)潜在地省略大量布局和渲染工作,直到需要它为止。

利用 content-visibility 的特性,我们可以实现如果该元素当前不在屏幕上,则不会渲染其后代元素。

如果有这个的Dom

<div v-for="item in items" :key="item">
   <div class="container-box">
      <p>-------------{
    
    {
    
     item.id }}-------------</p>   
      <img :src="item.src" alt=""/>
   </div>
</div>

<script>
export default {
    
    
  data() {
    
    
    return {
    
    
      items: [{
    
    
        id: 0,
        src: "http://g.hiphotos.baidu.com/image/pic/item/6d81800a19d8bc3e770bd00d868ba61ea9d345f2.jpg"
      },{
    
    
        id: 1,
        src: "https://gtd.alicdn.com/sns_logo/i3/TB1wnBTKFXXXXcQXXXXSutbFXXX.jpg_240x240xz.jpg"
      }, {
    
    
        id: 2,
        src: "//www.baidu.com/img/flexible/logo/pc/result.png"
      }, {
    
    
        id: 3,
        src: "http://e.hiphotos.baidu.com/image/pic/item/a1ec08fa513d2697e542494057fbb2fb4316d81e.jpg"
      }, {
    
    
        id: 4,
        src: "http://c.hiphotos.baidu.com/image/pic/item/30adcbef76094b36de8a2fe5a1cc7cd98d109d99.jpg"
      }, {
    
    
        id: 5,
        src: "http://h.hiphotos.baidu.com/image/pic/item/7c1ed21b0ef41bd5f2c2a9e953da81cb39db3d1d.jpg"
      }, {
    
    
        id: 6,
        src: "http://g.hiphotos.baidu.com/image/pic/item/55e736d12f2eb938d5277fd5d0628535e5dd6f4a.jpg"
      }, {
    
    
        id: 7,
        src: "http://e.hiphotos.baidu.com/image/pic/item/4e4a20a4462309f7e41f5cfe760e0cf3d6cad6ee.jpg"
      }, {
    
    
        id: 8,
        src: "http://b.hiphotos.baidu.com/image/pic/item/9d82d158ccbf6c81b94575cfb93eb13533fa40a2.jpg"
      }, {
    
    
        id: 9,
        src: "http://e.hiphotos.baidu.com/image/pic/item/4bed2e738bd4b31c1badd5a685d6277f9e2ff81e.jpg"
      }, {
    
    
        id: 10,
        src: "http://g.hiphotos.baidu.com/image/pic/item/0d338744ebf81a4c87a3add4d52a6059252da61e.jpg"
      }, {
    
    
        id: 11,
        src: "http://a.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee5080c8142ff5e0fe99257e19.jpg"
      }, {
    
    
        id: 12,
        src: "http://f.hiphotos.baidu.com/image/pic/item/4034970a304e251f503521f5a586c9177e3e53f9.jpg"
      }, {
    
    
        id: 13,
        src: "http://b.hiphotos.baidu.com/image/pic/item/279759ee3d6d55fbb3586c0168224f4a20a4dd7e.jpg"
      }, {
    
    
        id: 14,
        src: "http://a.hiphotos.baidu.com/image/pic/item/e824b899a9014c087eb617650e7b02087af4f464.jpg"
      }]
    }
  }
}
</script>

只需要给需要延迟(实时)渲染的元素,设置简单的 CSS 样式:

.container-box {
    
    
  content-visibility: auto;
}

但是它有一个缺点
滚动条在向下滚动在不断的抽搐,这是由于下面不在可视区域内的内容,一开始是没有被渲染的,在每次滚动的过程中,才逐渐渲染,以此来提升性能。

当然,其实使用 content-visibility: auto 并不能真正意义上实现图片的懒加载。

这是因为,即便当前页面可视区域外的内容未被渲染,但是图片资源的 HTTP/HTTPS 请求,依然会在页面一开始被触发!

扫描二维码关注公众号,回复: 15375979 查看本文章

因此,这也得到了一个非常重要的结论:

content-visibility: auto 无法直接替代图片懒加载,设置了 content-visibility: auto 的元素在可视区外只是未被渲染,但是其中的静态资源仍旧会在页面初始化的时候被全部加载。因此,它更像是一个虚拟列表的替代方案。

参考:https://github.com/chokcoco/iCSS/issues/185

使用 loading=“lazy” 和 decoding=“async” HTML属性实现图片懒加载

content-visibility略有瑕疵,还好我们有其他方式

loading="lazy"

HTML5 新增了一个 loading 属性。

到今天,除了 IE 系列浏览器,目前都支持通过 loading 属性实现延迟加载。此属性可以添加到 < img > 元素中,也可以添加到 < iframe > 元素中。

属性的值为 loading=lazy 会告诉浏览器,如果图像位于可视区时,则立即加载图像,并在用户滚动到它们附近时获取其他图像。

可以这样使用它

<img :src="item.src" alt="" loading="lazy"/>

这样,便可以非常便捷的实现图片的懒加载,省去了添加繁琐的 JavaScript 代码的过程。

loading=lazy 到(2023-02-26)的兼容性,还是非常不错的:
在这里插入图片描述

decoding="async

使用 decoding=async 实现图片的异步解码
除了 loading=lazy,HTML5 还新增了一个非常有意思的属性增强图片的用户体验。那就是 decoding 属性。

HTMLImageElement 接口的 decoding 属性用于告诉浏览器使用何种方式解析图像数据。

它的可选取值如下:

sync: 同步解码图像,保证与其他内容一起显示。
async: 异步解码图像,加快显示其他内容。
auto: 默认模式,表示不偏好解码模式。由浏览器决定哪种方式更适合用户。
上文其实也提及了,浏览器在进行图片渲染展示的过程中,是需要对图片文件进行解码的,这一个过程快慢与图片格式有关。

而如果我们不希望图片的渲染解码影响页面的其他内容的展示,可以使用 decoding=async 选项,像是这样:

<img :src="item.src" alt="" loading="lazy" decoding="async"/>

这样,浏览器便会异步解码图像,加快显示其他内容。这是图片优化方案中可选的一环。

同样的,我们来看看到(2023-02-26),decoding=“async” 的兼容性,整体还是非常不错的,作为渐进增强方案使用,是非常好的选择。

在这里插入图片描述

性能测试

检验 loading=lazy 与 decoding=async 效果

准备14张图片的页面,每个图片url大小不一

<template>
  <div class="container">
    <!-- loading="lazy" 懒加载 -->
    <div v-for="item in items" :key="item">
      <div class="container-box2">
        <p>-------------{
    
    {
    
     item.id }}-------------</p>   
        <img :src="item.src" alt="" loading="lazy" decoding="async"/>
      </div>
    </div>
  </div>
</template>

<script>
export default {
    
    
  data() {
    
    
    return {
    
    
      items: [{
    
    
        id: 0,
        src: "http://g.hiphotos.baidu.com/image/pic/item/6d81800a19d8bc3e770bd00d868ba61ea9d345f2.jpg"
      },{
    
    
        id: 1,
        src: "https://gtd.alicdn.com/sns_logo/i3/TB1wnBTKFXXXXcQXXXXSutbFXXX.jpg_240x240xz.jpg"
      }, {
    
    
        id: 2,
        src: "//www.baidu.com/img/flexible/logo/pc/result.png"
      }, {
    
    
        id: 3,
        src: "http://e.hiphotos.baidu.com/image/pic/item/a1ec08fa513d2697e542494057fbb2fb4316d81e.jpg"
      }, {
    
    
        id: 4,
        src: "http://c.hiphotos.baidu.com/image/pic/item/30adcbef76094b36de8a2fe5a1cc7cd98d109d99.jpg"
      }, {
    
    
        id: 5,
        src: "http://h.hiphotos.baidu.com/image/pic/item/7c1ed21b0ef41bd5f2c2a9e953da81cb39db3d1d.jpg"
      }, {
    
    
        id: 6,
        src: "http://g.hiphotos.baidu.com/image/pic/item/55e736d12f2eb938d5277fd5d0628535e5dd6f4a.jpg"
      }, {
    
    
        id: 7,
        src: "http://e.hiphotos.baidu.com/image/pic/item/4e4a20a4462309f7e41f5cfe760e0cf3d6cad6ee.jpg"
      }, {
    
    
        id: 8,
        src: "http://b.hiphotos.baidu.com/image/pic/item/9d82d158ccbf6c81b94575cfb93eb13533fa40a2.jpg"
      }, {
    
    
        id: 9,
        src: "http://e.hiphotos.baidu.com/image/pic/item/4bed2e738bd4b31c1badd5a685d6277f9e2ff81e.jpg"
      }, {
    
    
        id: 10,
        src: "http://g.hiphotos.baidu.com/image/pic/item/0d338744ebf81a4c87a3add4d52a6059252da61e.jpg"
      }, {
    
    
        id: 11,
        src: "http://a.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee5080c8142ff5e0fe99257e19.jpg"
      }, {
    
    
        id: 12,
        src: "http://f.hiphotos.baidu.com/image/pic/item/4034970a304e251f503521f5a586c9177e3e53f9.jpg"
      }, {
    
    
        id: 13,
        src: "http://b.hiphotos.baidu.com/image/pic/item/279759ee3d6d55fbb3586c0168224f4a20a4dd7e.jpg"
      }, {
    
    
        id: 14,
        src: "http://a.hiphotos.baidu.com/image/pic/item/e824b899a9014c087eb617650e7b02087af4f464.jpg"
      }]
    }
  }
}
</script>

CSS 的设置也很重要,由于是纯图片页面,如果不给图片设置默认高宽,最页面刷新的一瞬间, 元素的高宽都是 0,会导致所有 元素都在可视区内,所以,我们需要给 设置一个默认的高宽:

<style>
  img {
    
    
    margin: 8px;
    width: 202px;
    height: 166px;
    object-fit: cover;
  }
</style>

首先看看没有添加懒加载的效果(试验环境的网不太好)
](https://img-blog.csdnimg.cn/18943ccdd0594212b0fc319faae60f06.png)

可以看到,全部的图片资源在页面加载的过程中都请求了,页面 Load 事件完成的时间为 1.01s

现在我们为他加上 loading="lazy"decoding=async"

首次进入页面仅请求显示在屏幕上的图片,只发送了6个请求,页面 Load 事件完成的时间为 367 ms
在这里插入图片描述
页面滚动时,显示的图片才会继续发送请求

如果在图片量更大的情况下,优化效果会更加显著

猜你喜欢

转载自blog.csdn.net/weixin_52268321/article/details/131175291