在网站性能优化中,图像的影响比其他大部分内容都要严重。
本文我们来聊聊如何在前端工程化中优化图像。
原理
图像是由很多个像素点组成的,在电脑上以电脑方阵的形式表示。
也就是每个像素点对应一个 rgb 值。只有采取这种做法的图片格式才是真正未被压缩的格式,比如 bmp,全称 bitmap。
但是这种格式的图片体积过大,加载速度慢,已经逐渐被淘汰了。
如今主流的图片格式都是压缩过的图片格式,主流的比如 png 和 jpeg。
jpeg 压缩的思路是把一张图片切割成多个小格子,把每个格子中相同的 rgb 值转换为 YUV(亮度、色调、饱和度),再进行量化就可以降低图片的整体体积。
png 压缩的思路是复用相同的 rgb 值来降低体积。
但是在实际中具体的图像压缩过程非常复杂,本文不展开讲,我们主要来看看目前业界主流的做法。
主流打包器的做法
图像压缩时通常会有一个 quality 参数,表示质量,最低为 1,最高为 100。质量越高体积越大,质量越低体积越小。
通常建议为 75-80,不建议小于 60。
webpack 的压缩主要是依靠 image-minimizer-webpack-plugin 这个插件,它的底层依赖了 imagemin 这个库。
rollup由于更偏向于 JavaScript 库的打包,所以它会利用 @rollup/plugin-image 将图片打包成 base64 编码的格式,底层使用了 mini-svg-data-uri。
next/image 采用 sharp 来压缩图像,默认的质量是 75。
parcel 也是采用了 sharp 来压缩图像。
sharp vs imagemin vs jimp
我通过 npmtrends 对比了几个图像压缩库的使用趋势。
并且从其中又挑选了最主流的三个图像压缩库做对比,它们分别是 sharp、imagemin 和 jimp。
为了直观的对比它们的差异,我做了一个在线图像压缩的网站。
这个网站和其他图片压缩网站不同的地方是,它除了具备基本的 jpg、png 压缩、批量压缩、转换 webp、选择压缩质量以外,还可以选择不同的压缩器。
我选择了三张图片进行压缩对比:
格式 | 质量 | 压缩前 | 压缩后 | 转换 webp 后 | |
sharp | jpeg | 75 | 266kb | 138kb | 94kb |
imagemin | jpeg | 75 | 266kb | 114kb | 94kb |
jimp | jpeg | 75 | 266kb | 174kb | 不支持 |
sharp | jpeg | 75 | 557kb | 516kb | 239kb |
imagemin | jpeg | 75 | 557kb | 436kb | 239kb |
jimp | jpeg | 75 | 557kb | 682kb | 不支持 |
sharp | png | 75 | 66kb | 23kb | 9kb |
imagemin | png | 75 | 66kb | 19kb | 9kb |
jimp | png | 75 | 66kb | 88kb | 不支持 |
其实很好看出,imagemin 在 jpeg 和 png 的优化能力上最强,webp 模式下 sharp 和 imagemin 没有区别。jimp 会莫名其妙的负压缩。
jimp 的优势是不依赖 runtime 平台,它是零依赖的纯 JavaScript 实现。
sharp 和 imagemin 都依赖特定平台,但是它们在压缩能力上更加优秀。
不过 sharp 更加成熟和稳定,没有特殊要求,还是建议首选 sharp。
总结
作为打包网站类应用来讲的话,主流的方案很简单:
- 体积小的图片(通常指小于 10kb)转换为 base64。
- 体积大的图片(通常值大于 10kb)使用 webp 格式。
- 体积大但不是特别重要的图片,建议按照 75 的质量进行压缩。