上一篇文章介绍了Web前端性能优化(一),设计到的内容有:JS相关、渲染相关。今天我会接着上一篇来继续讲解Web前端性能的优化点。
1. 文件优化
- 图片优化
a. 计算图片大小
下面给大家举一个例子:
对于一张100 * 100像素的图片来说,图像上有10000个像素点,如果每个像素的值是RGBA存储的话,那么也就是说每个像素有4个通道,每个通道有1个字节(8位=1个字节),所以该图片大小大概为:10000 * 1 * 4 / 1024 = 39KB。
但是在实际项目中,一张图片可能并不需要使用那么多颜色去显示,因此我们可以通过减少每个像素的调色板来相应缩小图片的大小。
在了解了如何计算图片大小的知识后,那么对于如何优化图片,想必大家已经有2个思路了:
1)减少像素点;
2)减少每个像素点能够显示的颜色。
b. 图片加载优化
我们可以不使用图片。在一些时候会使用到很多修饰类图片,其实这些修饰图片完全可以用CSS去代替。
1)对于移动端来说,屏幕宽度就那么点,完全没有必要去加载原图浪费带宽。一般图片都用CDN加载,可以计算出适配屏幕的宽度,然后去请求响应裁剪好的图片;
2)小图可以使用base64格式;
3)将多个图标文件整合到一张图片中(即我们称的雪碧图,又叫css精灵);
4)选择正确的图片格式:
对于能够显示WebP格式的浏览器尽量使用WebP格式,因为WebP格式具有更好的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量,但是它的缺点是兼容性并不好;小图使用PNG格式,其实对于大部分图标这类图片,完全可以使用SVG代替;照片我们可以使用JPEG格式的。
- 其他文件优化
a. CSS文件放到head中;
b. 服务端开启文件压缩功能;
c. 将script标签放到body底部,因为js文件执行会阻塞渲染。当然也可以把script标签放在任意位置然后加上defer属性,表示该文件会并行下载,但是会放到HTML解析完成后顺序执行。对于没有任何依赖的js文件可以加上async,表示加载和渲染后续文档元素的过程将和js文件的加载与执行并行且无序进行。
d. 执行js代码过长会卡住渲染,对于需要很多时间计算的代码可以考虑使用Webworker。Webworker可以让我们另开一个线程执行脚本而不影响渲染。
- CDN
静态资源尽量使用CDN加载,由于浏览器对于单个域名有并发请求上限,可以考虑使用多个CDN域名。对于CDN加载静态资源需要注意CDN域名要与主站不同,否则每次请求都会带上主站的Cookie。
2. 网络相关
- 缓存
缓存对于前段性能优化来说是个很重要的点,良好的缓存策略可以降低资源的重复加载,提高网页的整体加载速度。
a. 实现强缓存可以通过两种响应头实现:expires和cache-control(注意:强缓存expires和cache-control同时存在时,则cache-control会覆盖expires,expires无论有没有过期,都无效。 即:cache-control优先级 > expires优先级。);
b. 如果缓存过期了,我们可以使用Last-Modified和If-Modified-Since、ETag和If-None-Match来解决问题。如果缓存有效会返回304,同样也需要客户端和服务器共同实现。(注意:对比缓存Etag和Last-Modified同时存在时,则Etag会覆盖Last-Modified,Last-Modified不会生效。即:ETag优先级 > Last-Modified优先级)
c. 选择合适的缓存策略。
注意:对于大部分的场景都可以使用强缓存配合协商缓存解决,但是在一些特殊的地方可能需要选择特殊的缓存策略:
a. 对于某些不需要缓存的资源,可以使用cache-control:no-store,表示该资源不需要缓存;
b. 对于频繁变动的资源,可以使用cache-control:no-cache并配合ETag使用,表示该资源已被缓存,但是每次都会发送请求询问资源是否更新;
c. 对于代码文件来说,通常使用cache-control:max-age=31536000并配合缓存策略使用,然后对文件进行指纹处理,一旦文件名改动就会立刻下载新的文件。
- 使用HTTP/2.0
因为浏览器会有并发请求限制,在HTTP/1.1时代,每个请求都需要建立和断开,消耗了好几个RTT(Round-Trip Time,即往返时延)时间,并且由于TCP慢启动的原因,加载体积大的文件会需要更多的时间。
在HTTP/2.0中引入了多路复用,能够让多个请求使用同一个TCP链接,极大的加快了网页的加载速度。并且还支持Header压缩,进一步的减少了请求的数据大小。
- 预加载
开发中,可能会遇到这样的情况:有些资源不需要马上用到,但是希望尽早获取,这个时候就可以使用预加载。
预加载其实是声明式的fetch(fetch是浏览器提供的原生 AJAX 接口。给大家一个链接:https://blog.csdn.net/crystal6918/article/details/53318194 ),强制浏览器请求资源,并且不会阻塞onload事件,可以使用以下代码开启预加载:
``
- 预渲染
以通过预渲染将下载的文件预先在后台渲染,可以使用以下代码开启预渲染:``
预渲染虽然可以提高页面的加载速度,但是要确保该页面百分百会被用户在之后打开,否则就白白的浪费资源去渲染。
3. 构建工具
使用webpack优化项目:
a. 对于webpack4,打包项目使用production模式,这样会自动开启代码压缩;
b. 使用ES6模块来开启tree shaking,这个技术可以移除没有使用的代码;
c. 优化图片,对于小图可以使用base64的方式写入文件中;
d. 按照路由拆分代码,实现按需加载;
e. 给打包出来的文件名添加哈希,实现浏览器缓存文件。