图片优化的价值
为什么要做图片优化?图片优化的收益有多大?
Google官方的最佳实践中关于图片优化有下面这样一段描述:
对于网页来说,在所下载的字节数中,图片往往会占很大比例。因此,优化图片通常可以卓有成效地减少字节数和改进性能:浏览器需要下载的字节数越少,对客户端带宽的争用就越少,浏览器下载内容并在屏幕上呈现内容的速度就越快。
那么图片到底占多大比例?
大家可以看一下http archive这个网站,它统计了世界范围内web资源的加载情况等信息。
2017年11月15日到2018年11月15日,一年内总的 web 资源的平均请求体积:
而关于图片的体积:
图片的体积大概占总资源体积的37%,图片在所有资源中占比是很大的,为此,我们也非常有必要优化图片的性能。
上面说的是全球网站的平均请求体积,下面我们拿我们自己的网上商城的网站看一下。
这是我们自己网站的首屏加载资源统计情况,可以看到图片体积占比更是达到了55.9%之高,这也非常符合电商网站的性质。(上图结果是通过WebPageTest测试得到)
我们发现,图片资源在网站所有资源中占比很大,而且在电商类网站中占比更大。优化图片可以减少客户端下载的字节数,改进网页性能。
图片类型和使用场景
常用的web图片格式有:JPEG/JPG、PNG、WebP、Base64、SVG
JPEG和JPG格式有什么区别?
没有区别,全名、正式扩展名是JPEG。但因DOS、Windows 95等早期系统采用的8.3命名规则只支持最长3字符的扩展名,为了兼容采用了.jpg。也因历史习惯和兼容性考虑,.jpg目前更流行。
JPEG/JPG
特点:有损压缩、体积小、加载快、不支持透明
适用场景:适用于呈现色彩丰富的图片,在我们日常开发中,JPG 图片经常作为大的背景图、轮播图或 Banner 图出现。
PNG
特点:无损压缩、质量高、体积大、支持透明
适用场景:PNG 在处理线条和颜色对比度方面有优势,主要用它来呈现小的 Logo、颜色简单且对比强烈的图片或背景等。
SVG
特点:文本文件、体积小、不失真、兼容性好
适用场景:将 SVG 写入独立文件后引入 HTML
Base64
特点:文本文件、依赖编码、小图标解决方案
适用场景:小图标,更新频率非常低,作为雪碧图的补充
WebP
WebP 是 Google 专为 Web 开发的一种旨在加快图片加载速度的图片格式,它支持有损压缩和无损压缩。
特点:全能但存在兼容性问题
使用场景:限制我们使用 WebP 的最大问题不是“这个图片是否适合用 WebP 呈现”,而是“浏览器是否允许 WebP”
图片优化方案
减少图片体积
- 采用WebP格式的图片,能够在不降低图片质量的前提下减小图片的体积。
WebP 的优势是它具有更优的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量;同时具备了无损和有损的压缩模式、Alpha 透明以及动画的特性,在 JPEG 和 PNG 上的转化效果都相当优秀、稳定和统一。
下左图JPEG(1.6M) 下右图WebP(1.2M)
cloudconvert可以在线转webp,大家可以去试一下。
WebP lossless images are 26% smaller in size compared to PNGs. WebP lossy images are 25-34% smaller than comparable JPEG images at equivalent SSIM quality index.
上文提到WebP虽然有诸多优势,但兼容性问题不得不考虑。在支持WebP的浏览器中优先使用WebP格式,否则采用默认格式。
看一下淘宝网站的做法,在Chrome浏览器下,采用的是WebP格式的图片,在Safari浏览器下,采用的是JPEG格式的图片。
看一下这两张图片的地址:
webp:https://img.alicdn.com/tfs/TB...
JPEG:https://img.alicdn.com/tfs/TB...
可以发现,淘宝是根据是否支持webp,动态设置(字符串截断)图片url的。
如何判断当前浏览器是否支持WebP?
可以参考谷歌网站的做法。
// check_webp_feature:
// 'feature' can be one of 'lossy', 'lossless', 'alpha' or 'animation'.
// 'callback(feature, result)' will be passed back the detection result (in an asynchronous way!)
function check_webp_feature(feature, callback) {
var kTestImages = {
lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",
lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
};
var img = new Image();
img.onload = function () {
var result = (img.width > 0) && (img.height > 0);
callback(feature, result);
};
img.onerror = function () {
callback(feature, false);
};
img.src = "data:image/webp;base64," + kTestImages[feature];
}
原理:对每一种格式的webp(有损,无损,alpha通道,动态)生成一个很小像素的图片,在浏览器中渲染,如果没有问题,就代表支持webp。
也可以让服务器端来判断返回什么格式的图片,服务器根据 HTTP 请求头部的 Accept 字段来决定返回什么格式的图片。当 Accept 字段包含 image/webp 时,就返回 WebP 格式的图片,否则返回原图。
- SVGO
利用SVGO压缩svg文件的大小,下面这张SVG原图80kb,利用SVGO压缩后是23kb。
缓存
谷歌最佳实践中指出:
对于静态素材资源或不常变化的素材资源,我们建议至少缓存 1 周,至多缓存 1 年。
如何使用缓存,有一张经典的图可以参考。
图片懒加载
懒加载的原理是:将图片的url赋值给img的data-url(可自定义)属性,监听滚动事件,当图片进入可视区域时,将data-url的值赋值给img的url属性,这时才真正发出图片的http请求。具体实现可以参考实现图片懒加载
响应式图片
一种可以在不同的屏幕尺寸和分辨率的设备上都能良好工作以及其他特性的图片
艺术方向:当你想为不同布局提供不同剪裁的图片——比如在桌面布局上显示完整的、横向图片,而在手机布局上显示一张剪裁过的、突出重点的纵向图片,可以用
分辨率切换:当你想要为窄屏提供更小的图片时,因为小屏幕不需要像桌面端显示那么大的图片;以及你想为高/低分辨率屏幕提供不同分辨率的图片时,都可以通过 vector graphics (SVG images)、 srcset 以及 sizes 属性来实现。
分辨率切换:不同的尺寸
分辨率切换: 相同的尺寸, 不同的分辨率
艺术方向
其他
- 利用雪碧图减少http请求
- base64编码内联小图片
- CDN加速
结语
性能优化需要了解其背后的原理,然后在项目中去实践,才能真正掌握。
参考文献
https://juejin.im/book/5b9365...
https://developers.google.com...
https://developers.google.com...
ps://httparchive.org/reports/page-weight#bytesTotal