背景是这样的,之前我们在展示我们的前端监控的时候,测试了一下公司的M站,发现性能打分还是比较差的,通过分析发现图片体积较大,但是其中有一张图片通过阿里云图片转成webp后体积缩小了90%
原图:
转webp:
而且看了一下webp支持:
发现safari并不支持,所以对于支持的浏览器使用渐进式处理
JavaScript检测是否支持WebP代码如下:(出自Google官方文档)
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的浏览器中打开页面速度明显提升,但是在实际测试中发现一个奇怪的现象:同样体积大小的图片,png比webp所花时间要短,why?
还原场景:
两张相同大小的图片
第一张:下载所需资源时间0.67ms
第二张:下载所需资源时间4.35ms
在解决上述问题时,我先去了解了一下,3种格式的含义
来自聊一聊几种常用web图片格式:gif、jpg、png、webp一文中关于图片格式的解析如下:
jpg
jpg是一种有损的基于直接色的图片格式。由于采用直接色,jpg可使用的颜色有1600w之多(2^24),而人眼识别的颜色数量大约只有1w多种,因此jpg非常适合色彩丰富图片、渐变色。jpg有损压缩移除肉眼无法识别的图片细节后,可以将图片的尺寸大幅度地减小。
但是jpg不适合icon、logo,因为相比gif/png-8,它在文件大小上丝毫没有优势。
png
png采用无损压缩,png相比gif对透明的支持更好,同等质量下,尺寸也更小。非常适合作为gif的替代品,但png也一个明显的不足就是不支持动画,因为其高品质,无损压缩,非常适合用于源文件或需要二次编辑的图片格式的保存
png与jpg一样能表达丰富的图片细节,文件大小至少是jpg的5倍,但在图片品质上的提升却微乎其微。所以除非对品质的要求极高,否则色彩丰富的网络图片还是推荐使用jpg。
webp
WebP图片是一种新的图像格式,由Google开发。与png、jpg相比,相同的视觉体验下,WebP图像的尺寸缩小了大约30%。另外,WebP图像格式还支持有损压缩、无损压缩、透明和动画。理论上完全可以替代png、jpg、gif等图片格式,当然目前webp的还没有得到全面的支持。
为了更具有说服力,不是偶发情况,我自己去模拟了几组格式,先将png转成webp,然后再将png的大小调成webp的大小
排除阿里云oss存储png转webp转换原因,使用webp转换工具(具体使用介绍)
brew install webp
cwebp [options] -q quality input.png -o output.webp
where quality is between 0 (poor) to 100 (very good).
Typical value is around 80.
得出自己实验数据(这里点击可以查看):
蓝色块是Conent Download 时间,就是我们需要的加载时间
取了三组数据如下展示:
第一组数据:
| 1.png | 1.jpg | 1.webp | 2.png | 2.jpg | 2.webp |
|---|---|---|---|---|---|
| 71.15ms | 85.44ms | 124.28ms | 224.17ms | 152.36ms | 248.19ms |
第二组数据:
| 1.png | 1.jpg | 1.webp | 2.png | 2.jpg | 2.webp |
|---|---|---|---|---|---|
| 72.74ms | 75.83ms | 120.34ms | 192.12ms | 185.15ms | 199.96ms |
第三组数据:
| 1.png | 1.jpg | 1.webp | 2.png | 2.jpg | 2.webp |
|---|---|---|---|---|---|
| 74.05ms | 68.70ms | 79.12ms | 157.50ms | 183.17ms | 186.15ms |
发现整体上webp的所花加载时间是这三种最长的,但是其中有些数据是异常的,10次中有1到2次数据与整体反常。
所以我猜测本身webp下载就是比jpg耗时长
来自探究WebP一些事儿一文中提到:根据Google的测试,目前WebP与JPG相比较,编码速度慢10倍,解码速度慢1.5倍。
有兴趣的可以去学习图片编码解码技术,其中webp用的是Libwebp-0.6.0编码技术
还有一个问题:浏览器 network的 content download 统计是否是准确?
答案是并不准确
const http = require('http');
var server = http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('1'); // ttfb
// res.write('2');
setTimeout(function(){
res.end('123'); // content download end
},5000);
});
server.listen({
port: 8888
})
一个很小的body片段,需要5秒钟!
其中res.write,根据node官网解释: 第一次调用 response.write() 时,它会将缓冲的响应头信息和主体的第一个数据块发送给客户端。 第二次调用 response.write() 时,Node.js 假定数据将被流式传输,并分别发送新数据。 也就是说,响应被缓冲到主体的第一个数据块。
不管怎么说,webp的超轻压缩体积对比这么点点瑕疵,实在是微不足道!本文主旨是在记录一次探寻为何同样体积大小的图片,png比webp所花时间要短的过程,webp还是非常推荐使用的!