网站作为一种信息传递的媒介,在如今各类的 Web 项目中,图像资源的使用占比越来越大,因此我们应当注意图像资源的使用方式。如果网站中的图像资源未进行恰当的优化,当网站访问量较大时会产生很大的带宽挑战,同时也会造成大尺寸图像请求时间过长等问题。
图像优化问题主要分为两个方面:图像的选取和使用和图像的加载和显示。本篇文章主要讨论图像的选取和使用。
图像基础
图像文件可分为两类:矢量图和位图,每种类型都有自己的优缺点和适用场景。
矢量图
矢量图中的图形元素被定义为一个对象,包括颜色、大小、形状及屏幕位置等信息。
矢量图适合于如文本、logo、控件图标及二维码等形状简单的几何图形。
矢量图的优点是能够在任何缩放比例之下呈现同样清晰的展示效果。
矢量图的缺点是对细节的展示效果不够丰富。对于足够复杂的图像,如果要达到照片的效果,通过 SVG 绘制会使得文件大的离谱,即便如此也很难达到照片的真实效果。
位图
位图是通过对矩阵中的栅格进行编码来表示的图像,图像的栅格像素点越多,且每个像素点所能表达的颜色范围越广,则位图图像整体的显示效果就会越逼真。
位图的优点是能提供较为真实复杂的细节体验,但位图会受屏幕分辨率的影响。
常见的位图有:JPEG、GIF、PNG、WebP
有损压缩和无损压缩
图像资源优化的根本思想是压缩,压缩是降低源文件大小的有效方式。图像压缩可分为有损压缩和无损压缩。
具体在选择压缩方式时,我们需要结合具体的业务需求考虑。如果业务上对图像的质量要求较高,则考虑使用无损压缩。
图像格式
JPEG
JPEG使用的是一种有损压缩算法。
用途:用作背景图、轮播图或者一些商品的 banner 图。但是由于有损压缩,当处理 Logo 或者图标时,需要较强的线条感或者强烈的颜色对比的时候,使用 JPEG 可能会出现边界模糊的不加体验,另外JPEG不支持透明度。
JPEG包含多种压缩模式,其中常见的有基于基线的和渐进式的。
- 基线模式:图像加载顺序是自上而下的,当网络较差时,图象是自上而下加载显示的
- 渐进式:将图像文件分为多次扫描,首先展示一个低质量模糊的图像,最后扫描到的图像信息不断增多,每次扫描过后所展示的图像清晰度也会不断提升
优缺点:渐进式解码速度要比基线慢,另外渐进式压缩得到的图像文件也不一定是最小的。
在实际生活中,我们不难发现,目前渐进式的 JPEG 已经慢慢取代了基线 JPEG 了。在应用时,我们可以使用一些第三方工具来创建渐进式的图像,例如 imagemin、libjpeg、imageMagick。以下是使用 gulp 创建渐进式 JPEG 的代码:
1 | const gulp = require("gulp") |
在执行后见流程之后,gulp 会调用 imagemin 的方法把 images 文件夹下所有的 jpg 图像全部进行渐进式编码处理。
GIF
gif 主要是动画图片,但是相比于视频文件,gif 在解码阶段十分耗时,所以出于对性能的考虑,我们应该尽量谨慎选用 gif。
PNG
PNG 是一种无损压缩的高保真图片格式,相比于 JPEG,PNG支持透明度,对线条处理更加细腻,并增强了色彩的表现,不过缺点就是文件体积太大。
优化 PNG:
对于 PNG 图像,我们可以使用 imagemin-pngcrush 来进行优化:
1 | const imagemin = require("imagemin") |
WebP
前面的三种图像文件格式,在呈现位图方面各有优劣:GIF 能呈现动画;JPEG 虽然不支持透明度,但是图像文件的压缩比高;PNG 虽然文件尺寸较大,但支持透明且色彩表现力强。
开发者在使用位图时对于这样的现状就需要先考虑选型。假如有一个统一的图像文件格式,具有之前格式的所有优点就好了。WebP 由此产生。
根据 WebP 官方网站给出的实验数据,当使用 WebP 有损文件时,文件尺寸会比 JPEG 小 25%-34%,而使用 WebP 无损文件时,文件尺寸会比 PNG 小 26%。
但是 WebP 存在一定的兼容性问题
从图中可以看出,除了 IE 浏览器不支持外,其他大部分浏览器都已经支持 WebP。
如何使用 WebP?
我们可以借助工具将原有的 jpg 或者 png 转换为 WebP 格式:
1 | loader: [{ |
这里值得注意的是,尽量不要使用低质量的 JPEG 格式进行转换,建议使用高质量的 JPEG 图像进行转换。
兼容性处理?
目前 WebP 不适用于所有浏览器,因此在使用时需要做兼容性处理。
通常处理的思路有两种:
一种是在前端通过 userAgent 判断浏览器版本,然后根据版本选择加载不同的图像。
另一种是可以通过
<picture>
标签来选择显示图像的格式,在<picture>
标签中添加多个<source>
标签元素,以及一个包含旧图像格式的<img>
标签,当浏览器在解析 DOM 的时候,便会对<picture>
标签中的多个图像源依次进行检测。如果都不支持,就会使用<img>
标记兼容显示出旧的图像格式。1
2
3
4<picture>
<source srcset="/path/image.webp" type="image/webp">
<img src="/path/image.jpg" alt="">
</picture>tips:
<picture>
标签的<source>
标签里面还可以有 media 属性,可以根据不同的 media 来显示不同大小的图像,因此<picture>
的常见使用场景:- 艺术指导(Art direction) —— 针对不同
media
条件裁剪或修改图像 - 遇到所有浏览器都不支持的特定格式时,提供不同的图像格式
- 艺术指导(Art direction) —— 针对不同
SVG
前面介绍的几种图像都是位图,而 SVG 是矢量图。SVG是基于 XML 语法描述图像形状的文件格式,适合用来表示 Logo 等图标图像。
Base64
Base64 是一种编码方式,它通过将图像的编码直接写入 HTML 或者 CSS 中实现图像的展示。
使用该方式编码展示的图像,无需发送 HTTP 请求,浏览器会自动解析并展示该编码图像。由于 Base64 编码原理的特点,一般经过 Base64 编码后的图像大小会膨胀四分之三。因此,只有对于小图而言,Base64 才能发挥它真正的作用。因此在考虑使用 Base64 编码时,要考虑以下几个条件:
- 图像文件的实际尺寸是否很小
- 图像是否真的无法以雪碧图的形式进行引入
- 图像文件的更新频率是否很低,以避免在使用 Base64 时,增加不必要的维护成本
格式选择建议
- 尽量使用矢量图,凡是用到图标的场景,应尽可能使用矢量图
- 对于位图使用的场景,首选 webp 格式
- 考虑到新技术的兼容性问题,使用 picture 标签进行适配,包含动画时,使用 GIF;需要展示细节并且需要透明度时,使用 PNG;追求更高图像压缩比时,使用 JPEG。此外对于不同缩放比的响应式场景,可以使用不同尺寸的图像,让浏览器根据实际情况进行调用。
总结
- 适合用矢量图的地方首选矢量图
- 使用位图时首选webp,对不支持的浏览器场景进行兼容处理
- 尽量为位图图像格式找到最佳质量设置
- 删除图像文件中多余的元数据
- 对图像文件进行必要的压缩
- 为图像提供多种缩放尺寸的响应式资源
- 对工程化通用图像处理流程尽量自动化