前端性能优化实践总结

本文提到的网站性能指网站的响应速度,这也符合绝大部分人对于网站性能的理解:访问快速的网站性能好,反之,访问速度越慢,则网站性能越差。本文总结的优化方法是宏观的工程层面的方法,并不包含微观的语言语法层面的方法,例如,JS、CSS的语法优化,这一部分同样影响网站的性能,但语言语法层面的优化更多的是取决于开发人员的编程水平。

什么样的网站响应速度快呢?其实很容易想到,网站加载资源的速度越快,网站响应速度越快;网站需要加载的资源越少,网站响应速度越快。这就分别对应网站性能优化的两大方向:资源缓存、资源合并压缩。当浏览器完成资源的加载后,需要进一步解析资源,才能渲染出最终的网页,所以,浏览器的解析机制也是网站性能优化的一个方向。各种优化方法都可以归类到这三个大方向中。

1.资源缓存1.1 使用CDN

将网站的静态资源分离,如静态HTML、图片Image、样式CSS、脚本JS等,把静态资源部署到CDN中,可以明显加快这部分资源的加载速度。

1.2 利用HTTP缓存机制

HTTP缓存会把浏览器加载过的资源缓存到本地,下次加载时,只要缓存的资源没有过期,就可以直接使用本地的资源,减少了HTTP请求次数,加快了资源加载速度。具体做法是设置HTTP Header 中的Cache-Control参数。HTTP 1.0 中使用Pragma和Expires两个参数进行缓存,不过早已不推荐使用。

2. 资源的合并压缩2.1 减少HTTP请求 vs 并行HTTP请求2.2 JS文件

合并压缩JS文件,一方面JS文件数量减少,需要的HTTP请求数也就减少了;另一方面,压缩JS文件可以极大地减小文件体积。可以使用webpack等Web构建工具对JS文件进行压缩合并。

要注意,压缩合并JS文件并不是要把所有的JS文件都打包到一个JS文件中。一般的做法是按照“基础代码”+“页面代码”分别打包。“基础代码”指各个页面或路由(对单页面而言)都要用到的通用代码,“页面代码”指在某个具体页面或路由中才会用到的代码。这样就可以实现JS代码按需加载,避免页面首屏加载时,因为单一JS文件过大,而影响首屏显示时间。对单页面应用来说,还可以有一个vendor.js的文件,这个文件中的内容是一些用到频率比较高的第三方库(如ECharts等),但这些库并不是每个路由都会用到的,所以并不会被打包到“基础代码”中。将这样的第三方库从各个路由页面对应的JS文件中拆分,一是可以减少所有JS文件的整体大小,因为本来可能是A、B等多个文件都会包含的代码,现在则只需要一份;二是vendor.js只需要被加载一次,后续打开其他路由时,就可以不需要再次加载这部分代码了,起到了资源预加载的作用。

2.3 CSS文件

对CSS文件进行合并压缩,基本原理和做法同JS文件。

2.4 图片

1) 使用WebP格式的图片。WebP是一种支持有损压缩和无损压缩的图片文件格式,派生自图像编码格式 VP8。根据 Google 的测试,无损压缩后的 WebP 比 PNG 文件少了 45% 的文件大小,即使这些 PNG 文件经过其他压缩工具压缩之后,WebP 还是可以减少 28% 的文件大小。

2)使用字体图标IconFont。可以任意设置Icon图形的大小和颜色。

3)使用CSS Sprites将多张小图片合并成一张,从而减少HTTP请求数量。

4)使用Base64直接把图片编码成字符串写入CSS文件,也是从减少HTTP请求数量考虑。但需要注意,Base64编码的图片最好是小图片(最好几十字节级别的),因为图片经过Base64编码后,一般会比原文件更大些。而且太长的Base64编码字符串也会影响CSS的整体可读性。

5)对于需要大量图片的网站,应该把图片资源单独部署,并使用不同的域名来访问。因为图片资源占带宽很大,如果把图片和其他资源部署到一台服务器或一个集群中,会占用很大的服务器端的出口带宽,从而影响到其他资源的下载速度。使用不同的域名加载图片资源,还可以更好的利用浏览器并行下载的特性,因为浏览器对于一个域名下的最大并行请求数是有限制的。

2.5 服务器端开启gzip

服务端开启gzip压缩,可以减少资源文件在网络传输过程中的体积大小。

3.浏览器加载、解析、渲染机制

当浏览器载入一个HTML文件后,

1)会对HTML进行自上而下的解析,同是会有另外的线程解析出 HTML中引用的所有外部资源(JS、CSS文件等),放到一个队列中,然后浏览器通过多个线程(具体由浏览器设置决定)并发加载这些资源,所以外部资源的加载和HTML的解析是并行进行的。

2)当解析到标签时,如果标签内是内嵌到HTML中的JS代码,会直接执行这部分代码;如果标签引用了外部的JS文件,且这个文件此时还没有下载完成,解析过程会被阻塞,直到JS文件下载完成,然后解析执行JS代码,之后才会继续HTML的解析过程;如果标签引用了外部的JS文件,但此时这个JS文件已经下载完成,则会直接执行这部分JS代码。

3) 当解析到

标签时,不管

中引用的外部CSS资源是否加载完成,都不会阻塞HTML继续向下解析。

这里有两个需要注意的地方:

1)因为JS的加载会阻塞HTML向下解析,所以多个JS文件中代码的执行顺序,是和他们在HTML中的位置顺序保持一致的。例如HTML中,从上向下依次引入a.js, b.js, a.js的文件大小远大于b.js,这样b.js文件很可能先完成加载,但是并不会先于a.js中的代码执行,因为在a.js加载、解析、并执行完成前,HTML的解析是处于阻塞的,b.js所在的标签自然也不会被解析执行。如果不希望加载外部JS文件阻塞HTML的解析,可以使用script标签的defer或async属性,这里就不再展开。

2)所有引用的外部脚本或样式文件,在HTML开始解析时,就加入到浏览器的请求队列中,所以多个外部资源开始加载的起始时间一般不会相差很大,除非请求的外部资源数量很多,超过了浏览器的并发请求数。

基于浏览器工作原理的常用性能优化方法有3个:

CSS放在head中,减小CSS文件大小,可考虑直接将首屏依赖的关键CSS内嵌到HTML中,然后异步加载其他次要CSS。

对于不依赖DOM的JS文件,设置async和defer属性进行异步加载(需要注意JS执行问题)。

当JS必须放到body内时,将JS放到body底部,保证首次绘制时可以呈现页面的骨架内容,减少用户的白屏感知时间。

如果想了解更多浏览器的工作原理,及其对页面性能的影响,可以观看我的视频课程:

浏览器工作原理及在网页性能优化中的应用

https://segmentfault.com/l/1500000015237807

以上就是从资源缓存、资源合并压缩和浏览器解析原理三个维度出发,常用的优化网站性能的实践方法。欢迎补充!

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180621G1NZ3Y00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券