图片优化方案

434 阅读12分钟

一、前端性能之图片优化

图片上传与下载是前端中常见的的业务场景。无论是前台还是后台,对图片进行适当的处理,都可以显著的提升用户体验。大家都知道,图片通常比文字更有吸引力,但通常体积大导致加载速度慢,相比于优化 JS 和 CSS,如何保证图片和文字更快展示是这次的主题。

现状

这里先给大家介绍 HTTP-Archive 这个网站,它会定期抓取 Web 上的站点,并记录资源的加载情况、Web API 的使用情况等页面的详细信息,对这些数据进行分析以确定趋势。通过它我们可以实时地看到世界范围内的 Web 资源的统计结果。

直观的看到,这十年来图片的体积越来越大。

而到了2021年,网页中图片的平均体积达900Kb左右,已经快占总体积的一半了。

方案

图片的优化处理方案有很多,包括选择合适的图片格式,图片压缩,CSS Sprites(雪碧图,CSS 精灵),图片懒加载,iconfont 字体图标,使用CDN等等。

不同业务场景图片格式的选择

时下应用较为广泛的 Web 图片格式有 JPEG/JPG、PNG、WebP、Base64、SVG 等,这些格式都是很有故事的,值得我们好好研究一把。此外,老生常谈的雪碧图(CSS Sprites)至今也仍在一线的前端应用中发光发热。

就这方面来说,与其说我们是在做“优化”,不如说我们是在做“权衡”。因为我们要做的事情,就是去选择尽可能体积小的图片格式、压缩它的体积。但这个优化操作,是以牺牲一部分成像质量为代价的。因此我们的主要任务,是尽可能地去寻求一个质量与性能之间的平衡点。

1)JPEG/JPG

特点: 有损压缩、体积小、加载快、不支持透明

优点

JPG 最大的特点是有损压缩。这种高效的压缩算法使它成为了一种非常轻巧的图片格式。当我们把图片体积压缩至原有体积的 50% 以下时,JPG 仍然可以保持住 60% 的品质。体积小,质量高。

此外,JPG 格式以 24 位存储单个图,可以呈现多达 1600 万种颜色,足以应对大多数场景下对色彩的要求,这一点决定了它压缩前后的质量损耗并不容易被我们人类的肉眼所察觉——前提是用对了业务场景。

使用场景

JPG 适用于呈现色彩丰富的图片,在我们日常开发中,JPG 图片经常作为大的背景图、轮播图或 Banner 图出现。

比如打开淘宝首页色彩最醒目的banner图,图片是以 .jpg 为后缀的

京东首页也是同样

使用 JPG 呈现大图,既可以保住图片的质量,又不会带来令人头疼的图片体积,适合表达更生动的图像效果,是当下比较推崇的一种方案。

JPG的缺点

有损压缩在上文所展示的轮播图上确实很难露出马脚,但当它处理矢量图形和 Logo 等线条感较强、颜色对比强烈的图像时,人为压缩导致的图片模糊会相当明显,此外,JPEG 图像不支持透明度处理,上述问题都可以召唤 PNG 来呈现。

2)PNG-8 与 PNG-24

特点: 无损压缩、质量高、体积大、支持透明

PNG 的优点

PNG(可移植网络图形格式)是一种无损压缩的高保真的图片格式。8 和 24,这里都是二进制数的位数。8 位的 PNG 最多支持 256 种颜色,而 24 位的可以呈现约 1600 万种颜色,颜色越多则体积越大。PNG 图片具有比 JPG 更强的色彩对比度,对线条的处理更加细腻,对透明度有良好的支持。它弥补了上文我们提到的 JPG 的局限性,唯一的 BUG 就是体积太大

总结的来说,不在意文件体积时,PNG-24是推荐的选择,但实际上为了避免体积过大,在适合PNG发挥的场景,我们通常优先选择更小巧的PNG-8。也尽量不用PNG处理复杂的图像。

应用场景

复杂的、色彩丰富的图片用PNG展示成本太高,不如交给 JPG。

而利用PNG在处理线条、颜色对比度方面的优势,用它存储 LOGO、颜色简单对比强的图片是很好的选择。

颜色对比强、尺寸不大的图,也适合PNG,这类图也是蛋卷首页用到最多的

3)SVG

特点: 体积小、不失真、兼容性好

SVG(可缩放矢量图形)是一种基于 XML 语法的图像格式。它和其它图片种类有着本质的不同:SVG 对图像的处理不是基于像素点,而是是基于对图像的形状描述。

优点

它最显著的优势是在于图片可无限放大而不失真这一点上,1 张 SVG 足以适配 n 种屏幕分辨率。同时,SVG是文本文件、它又可以写在HTML里,还能以独立文件 .svg的格式出现,这使得SVG的灵活性很强。从性能上看,对比JPG、PNG,SVG居然还有着文件体积更小,可压缩性更强的特点,看起来很美好。

局限性

1、虽然SVG的体积小,但渲染成本却很高,这对性能的不利导致它其实比正常图形加载更慢。2、SVG是可编程的,有更高的学习成本。

应用场景

  • 
    <svg xmlns="http://www.w3.org/2000/svg"   width="200" height="200">
        <circle cx="50" cy="50" r="50" />
    </svg>
    
    <img src="文件名.svg" alt="">
    
    

实际开发中,遇到SVG的地方是做生成图片需求时,用到的html2Canvas、domtoImage等库,原理是复制Dom->SVG->Canvas,最后调用 drawImage方法生成图片。

有趣的是Antd的< Icon >使用的就是SVG图标,舍弃了Iconfont,利用了离线存储、低端设备清晰度好等优点。

4)base64

特点:文本文件、依赖编码、小图标解决方案

Base64 并非图片格式,而是一种编码方式。就和雪碧图一样,它是作为小图标解决方案而存在的。

雪碧图将多个图标存储于一个文件,以减少HTTP请求次数为目的,Base64图片和它目的相同,只是方法不同,

应用场景

现在这儿有一个放大镜

image.png 要实现它,我们可以用传统方式

<img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/9/15/165db7e94699824b~tplv-t2oaga2asx-image.image">

那么浏览器就会针对img链接去发起一个资源请求。

但是如果我们对这个图片进行 Base64 编码,会得到一个这样的字符串:

data:image/png;base64,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

字符串比较长,我们可以直接用这个字符串替换掉中的src。浏览器原来是可以理解这个字符串的,它自动就将这个字符串解码为了一个图片,减少了一次 HTTP 请求。

在项目中搜索base64,发现用到的地方也不少,对应的往往是小的icon。我们的雪球LOGO就是base64格式的。

局限性

Base64能减少请求次数,为啥不把大图也换成base64呢? 主要原因是Base64编码后,图片大小会膨胀原来的 4/3 ,大图带来的体积浪费,与它节省的HTTP请求开销相比要大得多。所以当在以下场景更适合base64

1、图片尺寸很小 2、不适合用雪碧图 3、图片不用更新,没有代码维护成本

Webp

特点:年轻且全能

WebP 是今天在座各类图片格式中最年轻的一位,它于 2010 年被提出, 是 Google 专为 Web 开发的一种旨在加快图片加载速度的图片格式,它有损压缩和无损压缩都支持。

优点

WebP 像 JPEG 一样对细节丰富的图片信手拈来,像 PNG 一样支持透明,像 GIF 一样可以显示动态图片——它集各种图片文件格式的优点于一身。

与 PNG 相比,WebP 无损图像的尺寸缩小了 26%。在等效的 SSIM 质量指数下,WebP 有损图像比同类 JPEG 图像小 25-34%。 根据预测,全部图片替换webp后性能会提升约30%,既然是质量与性能的博弈,从这个角度看,WebP 无疑是最好的选择。

局限性

对浏览器来说,任何潮流的技术无论多好用,也要考虑兼容性,如果是三年前,WebP的兼容率只有73%,多少还有些不理想。到如今94%的浏览器兼容率,可以说值得一用了。

限制我们使用Webp的最大问题,不是图片是否适合用Webp存储,而是浏览器是否支持。既然选择了WebP,就得考虑safari、IE这些支持性不好的浏览器,要有对应的降级方案。

既要在支持 WebP 格式的浏览器中使用它,又要让不支持 WebP 的浏览器兼容。

方案1

pictrue 标签,和video一样,指定多个源由浏览器自行选择支持的。

<picture class="picture">
  <source type="image/webp" srcset="image.webp">
  <img class="image" src="image.jpg">
</picture>

方案2

淘宝、京东在商品列表中大量的使用到.jpg_.webp的后缀,在Chorme访问它是webp格式

image.png

而在Safari中,图片的后缀就变成了.jpg!可以猜想到,这个图片应该至少保存有 jpg 和 webp 两种格式,代码会判断浏览器的型号是否支持等信息,来决定显示的是 .webp 后缀还是 .jpg 后缀,在不支持的情况下,只需切割字符串就能达到降级JPG的效果。

image.png

方案3

服务端返回图片链接,判断根据 HTTP 请求头部的 Accept 字段来决定返回什么格式。当 Accept 字段包含 image/webp 时,就返回 WebP 格式的图片,否则返回原图。好处是灵活,即使浏览器兼容性改变,代码也不需要修改。局限性是后端可能不同意。

可以看到在网站有大量图片时,webp绝对是值得尝试的方案,更小的体积更好的性能,唯一要注意的就是兼容问题。

小结

上文中许多案例都取自电商网站,因为图片是电商网站占比极大的资源。在我们的业务场景下,有些选择就未必合适,比如蛋卷首页的内容以基金数据为主,本就不多的图片里,超过100K的就更少了,常见的运营位又以突出颜色对比度为主,选择PNG不失为好的选择。

image.png

参考资料:

1、juejin.cn/book/m/6844…

2、caniuse.com/?search=web…

3、juejin.cn/post/700203…

4、httparchive.org/reports/pag…