如何提高Web前端性能?

什么是WEB前端呢?就是用户电脑的浏览器所作的一切事情。咱们来看看用户访问网站,浏览器都作了哪些事情:输入网址 –> 解析域名 -> 请求页面 -> 解析页面并发送页面中的资源请求 -> 渲染资源 -> 输出页面 -> 监听用户操做 -> 从新渲染。

经过上面的路径能够看出浏览器分为请求、传输、渲染三部分来实现用户的访问,本文就从这三个部分来浅析如何提高WEB前端性能。javascript

请求css

浏览器为了减小请求传输,实现了本身的缓存机制。浏览器缓存就是把一个已经请求过的Web资源拷贝一份副本存储在浏览器中,当再次请求相同的URL时,先去查看缓存,若是有本地缓存,浏览器缓存机制会根据验证机制(Etag)和过时机制(Last-Modified)进行判断是使用缓存,仍是从服务器传输资源文件。具体流程以下图所示:html

如何提高Web前端性能?如何提高Web前端性能?

如何从请求、传输、渲染3个方面提高Web前端性能前端

浏览器的请求有些是并发的,有些是阻塞的,好比:图片、CSS、接口的请求是并发;JS文件是阻塞的。请求JS的时候,浏览器会中断渲染进程,等待JS文件加载解析完毕,再从新渲染。因此要把JS文件放在页面的最后。java

JS也能够经过两种方式由阻塞改为并行:一种是经过建立script标签,插入DOM中;另外一种是在Script标签中增长async属性。jquery

每种浏览器对同一域名并发的数量有限制,IE6/7是2,IE9是10,其余常见的浏览器是6,因此减小资源请求数量和使用多域名配置资源文件,能大大提升网站性能。ajax

减小资源请求数量的方法,大体有如下几种:express

一、经过打包工具,合并资源,减小资源数量。就是开发版本是不少个资源文件,部署的时候,按类合并成几个文件来输出。在实现模块管理的同时,实现统一输出。promise

二、CSS中,使用css sprite减小图片请求数量。浏览器

三、经过延迟加载技术,在用户无感知的状况下请求资源。

四、经过服务器配置,实现一次请求,返回多个资源文件,如淘宝CDN那样。

除了减小请求数量,也可使用CDN镜像,来减小网络节点,实现快速响应。使用了CDN的请求,会根据用户所处的地理位置,找寻最近的CDN节点,若是请求是新的,则从资源服务器拷贝到节点,而后再返回给客户端。若是请求已经存在,则直接从节点返回客户端。

经过上面咱们了解的缓存机制,若是咱们部署上线的时候,是须要刷新缓存的。普通缓存经过强刷就能改过来,而CDN缓存则须要经过改变URL来实现。同时咱们不可能要求用户按着Ctrl来刷新,因此经过打包工具,在部署的时候,统一更改URL是最有效的方式。而不常变动的库文件,好比echart、jquery,则不建议更改。

传输

从服务器往客户端传输,能够开启gzip压缩来提升传输效率。

Gzip有从1-10的十个等级。越高压缩的越小,但压缩使用的服务器硬件资源就越多。根据实践,等级为5的时候最均衡,此时压缩效果是100k能够压缩成20k。

渲染

浏览器在加载了html后,就会一边解析,一边根据解析出来的结果进行资源请求,并生成DOM树。而加载完毕的CSS,则被渲染引擎根据生成好的DOM树,来生成渲染树。等全部资源解析完毕计算好layout后,向浏览器界面绘制。随着用户操做,JS会修改DOM节点或样式,从新绘制和从新排列。从新绘制指的是绘制DOM节点对应的渲染节点,从新排列是指从新计算这些节点在浏览器界面的位置。很显然,重排是很是耗性能的。咱们要作的是减小重排的次数。

生成DOM树的时候,咱们能够经过减小DOM节点来优化性能。最初都是用table布局,节点深度和数量至关复杂,性能不好。一样CSS做为层叠样式表,层级也不可太深,否则遍历的成本很高。另外CSS的expression属性至关耗性能,能不用则不用。动画效果能用CSS写的就不用JS写,渲染引擎不同,性能损耗也不同。

上面说的是解析渲染的过程,咱们再接着说说用户交互操做的过程。用户操做就会致使重绘和重排,重排必定会引发重绘,而重绘不必定会引发重排。到底怎样会引发重排呢?简单的定义,DOM结构的变化,以及DOM样式中几何属性的变化,就会致使重排。几何属性顾名思义,就是宽、高、边框、外补丁、内补丁等俗称盒模型的属性。同时还有offset之类的边距属性。

重排是最耗能的,减小重排的方法有:

一、若是须要屡次改变DOM,则先在内存中改变,最后一次性的插入到DOM中。

二、同上一条,若是屡次改变样式,合成一条,再插入DOM中。

三、因为position的值为absoute和fixed时候,是脱离文档流的,操做此类DOM节点,不会引发整页重排。因此动画元素设置position使其脱离文档流。

四、当DOM节点的display等于none的时候,是不会存在于渲染树的,因此若是有比较复杂的操做,先使其display等于none,等待全部操做完毕后,再将display设成block,这样就只重排两次。

五、获取会致使重排的属性值时,存入变量,再次使用时就不会再次重排。获取这些属性会致使重排:offsetTop、offsetLeft、offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight

以上就是浏览器如何把资源变成肉眼所见的页面的,除了上述根据浏览器流程而总结出来的性能优化,咱们还须要看看javascript做为程序,须要的优化。先来看看javascript的垃圾回收机制。

Javascript的引擎会在固定的时间间隔,将再也不使用的局部变量注销掉,释放其所占的内存。而闭包的存在,将使引用一直存在,没法被释放掉。全局变量的生命周期直至浏览器卸载页面才会结束。因此通常来说,内存溢出就是因为全局变量的不释放和闭包引发。为了防止内存溢出,咱们能够作的方法有:

一、业务代码放在匿名当即执行函数里面,执行完毕会当即释放掉。

二、少用全局变量,同时用完的变量手动注销掉。

三、使用回调来代替闭包访问内部属性

四、当不可避免使用闭包时,慎重的对待其中的细节。不用的时候注销掉。

五、经过浏览器自带的工具profiles,来检查内存活动状况。若是是波浪型的,说明正常。若是是倾斜式渐进上涨的,说明有内存不会被释放,须要检查相应的函数。

最后再说一点,函数里返回异步取的值,常常有人这么:

 Var getList = function(){ $.ajax().then(function(data){

   Return data;

}) };

Var users = getList();

毫无疑问,因为函数内的返回是异步的,因此返回只能是undefined,而不是想要的data。因而为了实现返回data,就把ajax的async属性设置成了false,由异步改成同步,来获取到data。然而最大的问题来了,同步是会中断渲染进程的,也就是请求返回的等待中,整个页面是卡死的,用户操做也不会有响应。这个问题真正的解决方案是返回promise对象,而不是把异步改为同步。