网页性能的优化:
- 资源合并与压缩(html/css/js压缩合并)
- 图片相关优化(不同业务场景选择不同的图片格式,雪碧图等)
- css/js装载与执行(引用先后顺序及方式,是否阻塞,相互之间的依赖关系)
- 懒加载/预加载(dns预读取、多个CND域名、异步读取JS(script 的defer、async))
- 缓存优化
- 重绘与回流
...
网页性能测试工具
工具:Lighthouse是一个Google开源的自动化工具,主要用于改进网络应用(移动端)的质量。目前测试项包括页面性能、PWA、可访问性(无障碍)、最佳实践、SEO。Lighthouse会对各个测试项的结果打分,并给出优化建议,这些打分标准和优化建议可以视为Google的网页最佳实践。
工具安装:
- Chrome开发者工具(Devtools)的Audits,作为Chrome拓展程序使用,或者作为命令行工具使用(仅能在Chrome60及以上使用)
2.命令行工具:
npm install -g lighthouse
lighthouse https://example.com
// 配置项查看 lighthouse --help
常见的图片及特点
矢量图与位图
我们的电脑在显示图片的时候也可以分为这两种:矢量图与位图
- 矢量图:
(矢量:既有大小又有方向的量,也称为向量)
也称为面向对象的图像或绘图图像,矢量文件中的图形元素称为对象。每个对象都是一个自成一体的实体,它具有颜色、形状、轮廓、大小和屏幕位置等属性。
优点:
(1)文件小,图像中保存的是线条和图块的信息,所以矢量图形文件与分辨率和图像大小无关,只与图像的复杂程度有关,图像文件所占的存储空间较小
(2)图像可以无限缩放,对图形进行缩放,旋转或变形操作时,都不会不会产生锯齿效果或者模糊
(3)可采取高分辨率印刷,矢量图形文件可以在任何输出设备打印机上以打印或印刷的最高分辨率进行打印输出
缺点:
(1)难以表现色彩层次丰富的逼真图像效果
(2)暂时还不存在一种标准格式和标准处理流程,目前主要有SVG和Adobe Flash。因此处理矢量图只能靠CPU
适用场景:图形设计、文字设计和一些标志设计、版式设计等。
- 位图:
位图又叫像素图或栅格图,它是通过记录图像中每一个点的颜色、深度、透明度等信息来存储和显示图像。一张位图就好比一幅大的拼图,只不过每个拼块都是一个纯色的像素点,当我们把这些不同颜色的像素点按照一定规律排列在一起的时候,就形成了我们所看到的图像。所以当我们放大一幅像素图到一定程度时,能看到拼片一样的像素点
优点:
(1)利于显示色彩层次丰富的写实图像
缺点:
(1)一定程度的缩小或者放大都会让位图变形失真
(2)文件较大
我们在web页面中所使用的JPG、PNG、GIF格式的图像都是位图,即使他们都是通过记录像素点的数据来保存和显示图像,但这些不同格式的图像在记录这些数据时的方式却不一样,这就是涉及到有损压缩和无损压缩的区别——是否失真。
无压缩、有损压缩、无损压缩
- 无压缩。无压缩的图片格式不对图片数据进行压缩处理,能准确地呈现原图片。BMP格式就是其中之一。
- 无损压缩。压缩算法对图片的所有的数据进行编码压缩,能在保证图片的质量的同时降低图片的尺寸。png是其中的代表。
- 有损压缩。压缩算法不会对图片所有的数据进行编码压缩,而是在压缩的时候,去除了人眼无法识别的图片细节。因此有损压缩可以在同等图片质量的情况下大幅降低图片的尺寸。其中的代表是jpg。
聊一聊常见的web图片格式
- gif
GIF是CompuServe公司在 1987年开发的,是一种无损(100%的保持原始图片的像素数据信息)的8位(存储8位索引,也就是最多能表达2^8=256种颜色)图片格式,色彩复杂、细节丰富的图片不适合保存为gif格式。
特点:
(1) 透明特性:GIF支持基本的透明特性,这意味着你能够使图片的某些像素“不可见”。在其被放置到网页中时,我们就可以看到通过这些不可见区域看到此图片后面的背景颜色(图片)。
(2) 压缩特性:GIF格式采用LZW算法进行压缩,此算法是Unisys申请的一项专利。在十多年前,如果你想使用GIF格式,你还要给Unisys公司交专利费的。不过这项专利技术已于2003年6月20日过期,我们现在使用GIF是完全免费的。
(3) 快速加载特性:GIF同时也支持隔行扫描。隔行扫描能够令图片在浏览器中更快的加载和显示。这种特性能够提升慢网速用户的用户体验。
(4) 动画GIF:一个动态的GIF文件,是由若干帧图片所联结而成的动态图片。在显示时,这些动态帧被反复的绘制读取出来从而形成了简单的动画效果。
- jpg
是一种有损的基于直接色的图片格式,JPG(JPEG),文件后缀名为".jpg"或".jpeg",由于采用直接色,jpg可使用的颜色有1600w之多(2^24),而人眼识别的颜色数量大约只有1w多种,因此jpg非常适合色彩丰富图片、渐变色。jpg有损压缩移除肉眼无法识别的图片细节后,可以将图片的尺寸大幅度地减小。
特点:
(1)表现力强,能较好地摄影作品或写实作品;
(2)可以利用可变的压缩比来控制文件大小;
(3)JPG(JPEG)兼容性较好;
(4)有损耗压缩会使原始图片数据质量下降,当我们编辑和重新保存 JPG(JPEG) 文件时,JPG(JPEG) 会混合原始图片数据的质量下降。这种下降是累积性的;
(5)JPG(JPEG) 不适用于所含颜色很少、具有大块颜色相近的区域或亮度差异十分明显的较简单的图片(例如icon、logo,相比gif/png-8,它在文件大小上毫无优势)。
- png
png的产生一定程度上源于gif,初始是被当作gif的免费替代格式而生,采用公共专利压缩算法。
PNG-8:
是基于8位索引色的位图格式,最多只能索引256种颜色,所以对于颜色较多的图像不能真实还原;
特点:
(1)相比gif对透明的支持更好,同等质量下,尺寸也更小
(2)不支持动画
PNG-24:
是基于直接色的位图格式,可以保存1600多万种颜色,这基本能够真实还原人类肉眼所可以分别的所有颜色。
特点:
(1)png-24的图片质量堪比bmp,但是却有bmp不具备的尺寸优势
(2)因为其高品质,无损压缩,非常适合用于源文件或需要二次编辑的图片格式的保存
(3)图片存储为png-24比存储为jpg,文件大小至少是jpg的5倍,但在图片品质上的提升却微乎其微,所以除非对品质的要求极高,否则色彩丰富的网络图片还是推荐使用jpg
- webp
WebP图片是一种采用有损和无损压缩的图像格式,由Google开发,是基于VP8视频格式的衍生产品,目标是减少文件大小但达到和JPEG格式相同的图片质量,能够减少网络上的请求时间。
历史:
(1)该格式于2010年9月30日首次公布,作为网络上有损压缩真彩色图形的新开放标准,生成与旧JPEG方案相当的较小文件质量
(2)2011年10月3日,Google宣布WebP支持动画,ICC配置文件,XMP元数据和平铺(合成来自最大16384×16384平铺的非常大的图像)
(3)2011年11月18日,谷歌开始尝试无损压缩和无损和有损模式下的透明度(alpha通道)支持, 而在2012年8月16日的参考实做libwebp 0.2.0中正式支持
优点:
(1)与png、jpg相比,相同的视觉体验下,WebP图像的尺寸缩小了大约30%。(意味着更小的体积,更高的质量)
(2)WebP图像格式还支持有损压缩、无损压缩、透明和动画。理论上完全可以替代png、jpg、gif等图片格式
缺点:
(1)目前webp的还没有得到全面的支持,参考webp兼容性。
(2)根据Google的测试,目前WebP与JPG相比较,编码速度慢10倍,解码速度慢1.5倍(编码方面,一般来说,我们可以在图片上传时生成一份WebP图片或者在第一次访问JPG图片时生成WebP图片,对用户体验的影响基本忽略不计。
解码方面,WebP虽然会增加额外的解码时间,但由于减少了文件体积,缩短了加载的时间,页面的渲染速度加快了。同时,随着图片数量的增多,WebP页面加载的速度相对JPG页面增快了)
图片选择总结:
格式 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
gif | 文件小,支持动画、透明,无兼容性问题 | 只支持256种颜色 | 色彩简单的logo、icon、动图 |
jpg | 色彩丰富,文件小 | 有损压缩,反复保存图片质量下降明显 | 色彩丰富的图片/渐变图像 |
png | 无损压缩,支持透明,简单图片尺寸小 | 不支持动画,色彩丰富的图片尺寸大 | logo/icon/透明图 |
webp | 文件小,支持有损和无损压缩,支持动画、透明 | 浏览器兼容性不好 | 支持webp格式的app和webview |
附加
- FLIF是一种正在进行中的无损图像格式,声称在压缩率方面优于PNG,无损WebP,无损BPG和无损JPEG2000,于2015年推出
- BPG,一种图像格式,旨在成为JPEG图像格式的更高压缩效率的替代品,基于2014年推出的高效视频编码(HEVC)视频压缩标准的帧内编码
- HEIF,另一种基于HEVC的图像格式
- JPEG XR是2009年推出的支持HDR和宽色域空间的JPEG 2000的替代品
- JPEG 2000,一种改进,旨在取代2000年推出的JPEG委员会的旧JPEG
- MNG和APNG,基于PNG的动画图像格式,支持无损24位RGB颜色和8位alpha通道
- AV1静止图像文件格式,基于AV1视频编解码器的容器格式
如何将图片转化为webp
官方命令行
(1)WebP命令行工具安装:
Google提供了命令行工具用于将图片转换为webp
brew install webp
(2)使用cwebp将图像转换为WebP的格式:
/*** 参数可以参考:
https://developers.google.com/speed/webp/docs/cwebp
***/
cwebp [options] input_file -o output_file.webp
// 质量参数q,q为0~100之间的数字,比较典型的质量值大约为80, 默认75
// 在有损压缩(默认)的情况下,较小的因子会产生质量较低的较小文件。
// 在无损压缩(由-lossless选项指定,对图像进行编码而不会有任何损失)的情况下,较小的因素可以实现更快的压缩速度,但会产生更大的文件。
cwebp -q 80 WechatIMG4.jpeg -o 11.webp
- 有关编码器,其标准和高级选项的说明,请参考编码文档
- 输入格式可以是PNG,JPEG,TIFF,WebP或原始Y'CbCr(有时候也被写作YCBCR,是色彩空间的一种,通常会用于影片中的影像连续处理,或是数字摄影系统中)样本。
(3)使用dwebp从WebP的格式转换为png(默认)图像:
/*** 参数可参考:
https://developers.google.com/speed/webp/docs/dwebp
***/
dwebp in_file [options] [-o out_file]
// -o 指定输出文件的名称(默认为PNG格式)
dwebp 11.webp -o convertback.png
- 有关解码器及其命令行选项的说明,请参考解码文档
- dwebp 将WebP文件解压缩为PNG,PAM,PPM或PGM图像
(4)gif2webp:将GIF图像转换为WebP
/***
参数参考:
https://developers.google.com/speed/webp/docs/gif2webp
***/
gif2webp [options] input_file.gif -o output_file.webp
gif2webp -q 70 phone.gif -o phone.webp
(5)img2webp:从一系列输入图像创建动画WebP文件
/***
参数参考:
https://developers.google.com/speed/webp/docs/img2webp
***/
/*** 文件级选项 -loop int :
指定动画应循环的次数。使用0手段'无限循环'
-lossless, -lossy:
使用无损或有损压缩模式压缩下一个图像。默认模式是无损的
***/
img2webp -loop 0 pddlogo.png -lossy tblogo.png -d 80 -o out11.webp
(6)vwebp :解压缩WebP文件并使用OpenGL在窗口中显示它
/***
参数参考:
https://developers.google.com/speed/webp/docs/vwebp
***/
vwebp [options] input_file.webp
vwebp picture.webp
(7)webpinfo:用于打印出WebP文件的块级结构和比特流头信息。它还可以检查文件是否是有效的WebP格式
/***
参数参考:
https://developers.google.com/speed/webp/docs/webpinfo
***/
webpinfo out11.webp
(8)webpmux:从非动画WebP图像创建动画WebP文件,从动画WebP图像中提取帧,以及管理XMP / EXIF元数据和ICC配置文件
/***
参考地址:
https://developers.google.com/speed/webp/docs/webpmux
***/
// 从动画WebP文件中获取第1帧
webpmux -get frame 1 out11.webp -o frame_2.webp
// 把获取到的图片转化成png
dwebp frame_2.webp -o convertbackframe_2.png
相关在线转化工具
- 智图
- 又拍云
- CloudConvert
- isparta
- ...
canvas生成
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
img = document.getElementById('img');
var loadImg = function(url, fn) {
var image = new Image();
image.src = url;
image.onload = function() {
fn(image);
}
}
loadImg('image url', function(image) {
canvas.height = image.height;
canvas.width = image.width;
ctx.drawImage(image, 0, 0);
img.setAttribute('src', canvas.toDataURL('image/webp'));
});
gulp-WebP或gulp-imageisux
- gulp-WebP
// 有损压缩图片设置webp插件的quality参数,无损压缩设置lossless参数为true即可
var gulp = require('gulp');
var webp = require('gulp-webp');
gulp.task('default', ()=> {
gulp.src('./*.{png,jpg,jpeg}')
.pipe(webp({quality: 80}))
.pipe(gulp.dest('./dist'));
});
- gulp-imageisux
/***
dirpath 目标目录:如果未定义,会自动生成两个目录:'/dest/'目录放压缩后图片,'/webp/'目录放对应的webp格式压缩图片
enableWebp 是否同时导出对应WEBP格式图片:若为true,则会同时输出webp图片;若为false,则只会有压缩后原格式图片
***/
var imageisux = require('gulp-imageisux');
gulp.task('imageisux', function() {
return gulp.src(['img/*'])
.pipe(imageisux('/dirpath/',enableWebp));
});
如何判断浏览器是否支持webp
- HTML5 picture(picture 兼容性
)
这种方法不进行 WebP 支持程度的判断,而是利用 html5 picture 元素的特性,允许开发者列举出多个图片地址,浏览器根据顺序展示出第一个能够展现的图片元素,如:
// 在浏览器不支持 WebP 图片的情况下自动回退到 jpg 格式进行展示
- 嗅探
是指直接向浏览器中插入一段 base64 的 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 图片的嗅探,这是一种最为保险的方法。不过缺点也很明显,在图片类型不一且量级较大的情况下,前端并不能知道哪些图片是有损,无损,亦或是透明的,也没有办法对其中一种特定类型做特定策略,所以即使知道不支持该类型的 WebP,然而我们也没有办法主观的去做容错。所以这种方法只适合于图片类型单一的情况,如开发者知道所有图片都是有损的,或是动图等,有针对性的去处理。
同时在处理的过程中,为了提高嗅探效率,嗅探之后可以将结果以本地存储的方式进行保存,如cookie ,方便下次直接进行调用
- Request Header:是较为符合标准的解决方案
浏览器在支持 WebP 图片格式的情况下,会在请求的 http header accept 中携带 webp/image 的字段,后端接收到请求之后可以按照该形式来判断是否返回 WebP 图片内容;
坑——国内浏览器层出不群,大部分都向标准化的方向靠近,但仍然需要一定的时间来跟进。所以,在实践过程中我们就发现了这样的问题:虽然 http header accept 中包含了 webp/image 的字段,但实际上是不支持 WebP 格式的(华为 MT7 自带浏览器),具体体现在动图(animation)的 feature 上。而相应的解决方案如下:
- 预先存储:直接把图片转化成webp格式的 放到项目目录里面 ,页面上直接请求webp的图片格式,这时候服务器只需要配置nginx对webp格式支持就好;
- 实时转换:我们项目目录里面放png的图片,比如1.png ,页面访问 1.png.webp ,这时候需要nginx对域名进行拦截,lua脚本进行域名后缀规则的匹配,比如说300x300.png/.webp类似的后缀,匹配完成后再在lua里调用graphicsmagick的命令,进行一些图片转换、裁剪等工作,此方案转化过程较慢
附加:
针对不支持webp的可以参考:
http://webpjs.appspot.com/
总结
WebP 作为一种新型图片格式,不但能够节省流量,减少图片体积,一定程度上也可以优化用户体验,越来越多的浏览器都开始支持使用,但是根据不同的场景和需求,使用需要谨慎。