前端性能优化之图片优化方案梳理

lxf2023-04-07 18:16:01

前言

随着手机或者电脑设备的不断升级性能逐渐在提升,设备可支持的前端技术也更加强大,再加上很多简单的图片可以使用 CSS 或者 Canvas 等技术来进行绘画,对图片的需求其实是在逐渐变小的,我们可以看一下一组数据(中位数):

前端性能优化之图片优化方案梳理

可以看出图片请求的数量是是逐渐变少的。

但现阶段不可能完全依靠技术来替代图片,在很大部分的网页中仍然占据很重要的地位,且随着图像技术的发展,图片质量现在也越来越好,体积也就越来越大,图片仍然会是“影响页面的性能,导致加载速度变慢,影响用户体验”的重要原因之一。

页面下载总字节数(中位数):

前端性能优化之图片优化方案梳理

页面图片下载总字节数(中位数):

前端性能优化之图片优化方案梳理

上面数据来源于 http archive。

因此图片性能体验优化仍然是前端开发中非常重要的一部分,并且可以预料的是未来很长时间都将如此。

图片优化的方式梳理

图片优化一般都是指的是优化图片本身的体积大小和图片呈现速度,体积小加载速度就会更快,对用户的流量消耗也会小很多,不要小看这点流量,现在的图片质量越来越好,一张图片经常都是几兆甚至更多,浏览一个网页下来,要是不进行优化,用户就消耗了几十兆上百兆流量,这也是很影响用户体验的(要是没有链接 Wi-Fi ,流量都不够用的)。

常见的图片优化方式有以下几种:

  • 压缩图片
  • 雪碧图(比较老的方式了,现在一般不推荐)
  • 图片懒加载和预加载
  • 使用合适的图片尺寸
  • 使用 CDN 缓存图片
  • 使用合适的图片格式

下面将针对这几种方式来说明一下。

压缩图片

压缩图片主要就是为了降低图片的体积大小,是优化性能的主要方法之一,图片压缩的时机一般分为 使用前压缩构建时压缩

使用前压缩 指的是图片在上传或者使用到项目中前进行先压缩,可以使用许多在线工具来压缩图像,比如 TinyPNG 、Kraken.io ,当然也可以在代码提交到 git 前进行自动处理。

构建时压缩 指的是在使用打包工具进行打包时进行压缩文件,保留图片原文件,比如使用 webpack 就可以使用 image-webpack-loader 来对图片进行压缩。

雪碧图

雪碧图原名叫 CSS sprites ,是指把多张小的的图片内容拼在一张图片上,每次请求只用请求拼接后的这张图片,然后使用css控制图片的显示位置来显示不同的内容的一种图片性能优化方式。

这是一种比较古老的优化方式了,但在 HTTP/1 的广泛使用的时代,它对页面的性能也起到了很大的作用,因为 HTTP/1 的每个请求都会新建一个TCP连接,每个域名同时最多同时有6个TCP连接,会造成 TCP 连接之间相互竞争带宽,而且启动TCP连接相对较慢,因此当图片尺寸较小,显示图片数量又较多时,会对页面性能造成很大的影响,这时候使用雪碧图就可以极大的减少图片资源对网络请求造成的阻塞。

不过在随着 HTTP/2 的普及,使用雪碧图已经不再是必要性能优化的方式了。因为 HTTP/2 实现了多路复用功能,解决了 TCP 协议慢启动和最多 6 个 TCP 连接的问题,因此不在需要去过多关注请求数量造成的一些性能问题。

图片懒加载和预加载

图片懒加载指的是:当图片不在屏幕显示范围内时,不需要发起图片资源请求,在图片即将出现在屏幕中时再去加载图片资源。

当然一般我们不会在图片需要出现在屏幕范围内时再去图片资源,而是在屏幕外一屏距离的时候就会提前去请求图片资源,这样可以让图片更快的呈现在用户屏幕。

图片懒加载不仅是一个性能优化的重点,也是体验优化的重点,图片懒加载可以减少页面对网络的压力,让网络更优先的处理其他关键资源,让页面可以更快的显示更完整的内容,而且也可以减少用户的流量及电量消耗。

图片懒加载实现方式有两类方式:

  1. 监听滚动距离 ➕ 元素自身相对页面的位置,来判断元素是否即将出现在屏幕中,是的话就加载图片资源
  2. 使用 IntersectionObserver 来直接监听自身是否出现在设定的距离屏幕的范围来判断是否加载图片资源。

更推荐使用 IntersectionObserver ,因为它的性能会更好,不过兼容性会差一些,但在现在浏览器上兼容性也算比较好了,也有 polyfill 可以使用。

前端性能优化之图片优化方案梳理

具体实现方式可以去看一下我之前写的一篇关于 图片懒加载 的文章可以看看。

图片预加载指的是预先请求暂未访问的图片资源,这样可以当用户访问时,更快的把内容呈现给用户,但需要注意资源的大小,以及使用的可能性,否则会浪费用户流量,使用的场景也挺多的,比如在一些游戏页面,游戏资源一般会依赖大量图片,因此需要在显示加载页面的时候,预先去下载游戏所需要的主要图片资源。

之前也写了一篇关于 图片预加载实现 的文章,感兴趣的可以去看看。

使用合适的图片尺寸

在使用图片之前,尽量确认图片需要显示的大小和分辨率(设备像素比)。如果需要显示一个较小的图像,尽量不要使用很大的图片并使用限制宽高的方式来缩小它,当然如果是移动端,因为分辨率导致设备像素比的不同,因此需要显示图片往往是实际尺寸的2倍或者3倍。

因此我们可以通过使用合适大小的图片来减少图片文件的体积,优化加载时间。

使用 CDN 缓存图片

内容分发网络(CDN)是一组分布在多个不同地理位置的 Web 服务器。当服务器离用户越远时,延迟就越高。CDN 就是为了解决这一问题,在多个位置部署服务器,让用户离服务器更近,从而缩短请求时间。因此 CDN 也可以用来加速图像的交付,减少图片请求的网络延迟。

使用合适的图片格式和图片裁剪说明

我们一般常用的图片格式有以下几种:

  • jpeg(jpg) 适合色彩丰富的图像,不过由于它每个像素的数据是以 RGB 的形式来存储,因此不支持透明色
  • png 适合色彩较少或者单一图像,以 ARGB 的形式存储,支持透明色
  • gif 显示动态图,支持透明色
  • svg 可缩放矢量图形,是一种无损格式,意味着它在压缩时不会丢失任何数据,放大也不会出现模糊。常用于 LOGO 、图形设计和可视化图表等等色彩相对简单的场景。
  • webp 一种新型的图像格式,它比 jpeg 和 png 格式具有更小的文件大小,因此往往可以提示图片的加载速度。许多现代浏览器如Chrome、Opera、Firefox 和 Edge 都支持 webp 格式,兼容性较好,但 Safari 浏览器兼容性较差,因此如果用户包含 IOS 用户,使用的时候需要错一些兼容处理。

下面我们来对比一下同一内容的图像使用 jpeg 和 webp 格式的差别。

前端性能优化之图片优化方案梳理

webp 格式是使用 又拍云 工具把 jpeg 转化生成的,可以看出,图片尺寸、内容完全一样,清晰度也一样,但是图片的体积只有 jpeg 的十分之一左右(不是所有的图片都是体积都压缩到这个程度,有的会更小一些,有的篇大一些,但都会比原图片小很多)。

其他免费图片转换工具推荐一下 aconvert ,可以用来转换各种图片格式,也可以转换视频为 gif。

这里需要注意的点是,webp图片的传输效率并没有 jpg/png 高,但因为体积缩小的原因,整体下载时间还是比 jpg/png 快很多。

因此,建议使用 jpeg/png/gif 格式的图片时,完全可以转化成 webp 来使用,如果是已上传的图片,也可以开启图像处理功能,现在一般的云服务商也都会提供相当全面的图像处理功能,阿里云和腾讯以及 aws 等云服务商都是有转换图片格式的功能。

阿里云服务转换webp和图片裁剪功能

这里将以阿里云为例,来讲解怎么去开启 webp 转换功能和图片格式兼容性处理的原理

阿里云开启 webp 格式有两种情况,一种是开启 CDN 的自适应 webp 的功能,需要打开图像处理,选中弹出中的自适应 webp 选项:

前端性能优化之图片优化方案梳理

开启这个选项后,CDN 服务器会根据请求头上的 Accept 字段来判断浏览器是否支持 webp 格式来决定是返回原图片格式还是 webp 格式,支持的情况下一般会出现 image/webp 关键字:

前端性能优化之图片优化方案梳理

阿里云 CDN 的图像处理现在还是免费的,但以后有可能会付费。

还有种方式就是如果你使用的是阿里云 OSS 存储的图片,那么可以传递官方文档提供的参数来进行图像处理。比如:

https://xxx.png?x-oss-process=image/resize,w_100,h_100/format,webp/quality,q_80

在图片链接上新增 x-oss-process 参数,此参数的值可以传递图像处理的子参数,子参数通过 / 分割,子参数有:

  • image 表示文件类型。
  • resize,w_100,h_100 表示图片裁剪方式为resize 表示缩放图片,不对图片进行裁剪,需要的图片宽度为 100px,图片高度为 100px
  • format,webp 表示需要的图片格式为 webp
  • quality,q_80 表示需要的图片质量为 80,原图为 100,越低图片越小,越不清晰。

上面不仅描述了图片的格式,也定义了需要的图片裁剪方式、大小和质量,这些参数在实际运用也很有用。

OSS 并没有根据请求头上的 Accept 字段来提供兼容性处理,因此需要自己做一些处理,处理方式也可以参考 CDN 自适应 webp 的处理方式,或者在客户端请求前进行判断浏览器是否兼容 webp 格式,也可以考虑能否结合 CDN 的图片处理功能进行整合。

webp 也可以这样进行兼容:

<picture>
  <source type="image/svg+xml" srcset="pyramid.svg" />
  <source type="image/webp" srcset="pyramid.webp" />
  <img
    src="pyramid.png"
    alt="regular pyramid built from four equilateral triangles" />
</picture>

浏览器会检测支持的格式,以便于使用合适格式的图片,尝试了一下,有效,但实际环境使用起来还是会麻烦一点,方案源于 MDN 响应图像。

总结

图片作为现代网站重要元素之一,优化图片性能是前端性能优化中很关键的一部分,不过随着技术的发展,也许会出现一些新的优化方式替代以前的一些优化方式,但性能优化的关键还是以提升用户体验为目的,把握关键即可。

去年写过一篇关于前端性能优化总结文章,感兴趣的可以去看一下:web前端性能优化——实践总结篇

有问题欢迎评论区提出,感谢纠错!

本文正在参加「」