一,性能问题的简单分析、直接表现、根本原因
简单分析:
首先,一个完整的页面主要由两部分组成,一是UI,二是数据。如果按照MVC架构,或是数据与表现分离的思想,还可以细分成三部分。一是通过html(结构)+css(表现)渲染出来的UI层(view),二是通过http来完成的数据层(model),三是将数据填充到view或者DOM操作的控制层(controller)。
于是,一次完整的页面加载就可以分成三部分工作,一是view渲染(UI),二是数据加载(http),三是数据填充到view或更改(DOM操作)。其中只要有一个环节出问题,都有可能造成性能问题。
综上所述,我们可以总结出三个主要可能造成性能问题的环节:UI渲染、http请求、DOM操作。
总而言之,要优化性能问题,就需要对可能造成性能问题的环节逐个击破。
直接表现:
1,页面加载时间过长
2,卡顿、闪现、页面结构错乱等现象
根本原因:
1,DOM结构复杂
2,过度或不恰当的DOM操作
3,http请求过多、请求时间过长、请求异常(中断、无响应、请求错误)等情况
下面,针对以上可能造成性能问题的环节,进行逐个优化。
二,性能优化之——DOM结构优化
1,保证简洁、清晰的html结构,减少或避免多余的html标签
2,使用HTML5的web语义化标签,保证结构清晰,同时利于seo
3,避免过于复杂的DOM结构,避免过度嵌套
4,采用SPA(单页应用)模式开发,动态按需加载
三,性能优化之——DOM操作优化
1,理解DOM操作:
为什么DOM操作会引起性能问题?
首先,每次DOM操作,页面DOM结构通常都有可能会被改变,浏览器一旦检测到DOM结构发生改变,就会进行全局的重绘,相当于每次DOM操作都对页面重新渲染了一遍。
因此DOM操作的过程其实是页面不断重复渲染的过程,如果这个过程很复杂,或者操作频繁,或逻辑错误,就会造成性能问题。
可是,DOM操作是不可避免的,于是我们优化的思路是减少DOM操作频率。
2, 减少DOM操作的方法:
(1) 使用innerHTML属性替代DOM操作
innerHTML不会进行全局的重绘,而是局部重绘,因此对性能影响较小。
(2) 使用react、vue等性能较好的框架
这类框架都对DOM操作进行过特殊处理,性能较好。以react为例,react内部将虚拟DOM、diff算法、
innerHTML三者结合起来处理DOM操作,避免了用户直接操作DOM。
(3) 避免或减少使用jquery等DOM操作库
四,性能优化之——http优化
http性能优化方法:优化静态资源和api请求。
(一) 理解http请求
1,理解http请求的类型
http请求分两大类,一类是静态资源请求,另一类就是api请求(请求后台接口)。
** (1) 静态资源请求 **
所谓静态资源请求,就是页面加载时从服务器下载html、css、js、图片等静态资源文件。
静态资源请求,如下图:
** (2) api请求 **
所谓api请求,就是请求后台的接口所发出的http请求。如下图:
简而言之,http性能优化,其实是对静态资源(html、css、js、图片)和api请求的优化。
2,理解http请求带来的性能问题:
如果你理解http工作原理,那应该知道每次http请求过程的复杂性,代价是很高的。
因此,如果出现http请求过多、请求时间过长、请求异常(中断、无响应、请求错误)等都有可能会对性能造成影响。
下面就针对http请求的优化方案展开讲解。
(二) 静态资源优化
静态资源有html、css、js、图片等类型。因此要对它们进行分门别类地优化。
如果请求的静态资源过多、过大、或不存在等,都可能会造成性能问题。
静态资源优化的办法,就是对静态资源进行切割、合并、压缩等处理,以达到缩小静态资源体积、减少静态资源请求次数等目标,以实现快速完成http请求的过程。
下面对静态资源优化,分门别类来讲解。
1,html结构优化
(1) 保证简洁、清晰的html结构,减少或避免多余的html标签
(2) 使用HTML5的web语义化标签,结构清晰且利于seo
(3) css文件在head中引入,js文件放在body底部引入,这样做可以防止阻塞。另外如果有需要提前加
载的js,请在window.onload方法中处理。
解释: 浏览器加载js文件时其他一切渲染活动都会停止,直到js文件下载完成, 如果把js文件放头部
加载,就会造成阻塞,也就是加载js时会阻止页面渲染。 因此通常js文件需要放body底部加
载,等页面渲染完成后再加载js文件。
2,css优化
(1) 使用gulp、webpack等构建工具,对css进行合并、压缩等处理,以缩小css文件体积
(2) 如果你的应用css样式很庞大,可拆分成多个css文件,并做压缩处理,避免单个css文件过大
(3) 如果使用webpack,推荐使用extract-text-webpack-plugin之类的插件将css样式抽离出来,防止其随js一起打包
(4) 如果使用react、vue等框架,推荐使用css-modules、css in js等css模块化解决方案。
(5) 使用sass/less等预编译处理方案(后期不推荐使用,推荐使用css模块化方案)
(6) 尽量减少或避免使用内联样式
(7) 对于一些需要复杂计算的样式,比如box-shadow、import等,减少使用。
(8) 使用css3动画时,请开启GPU硬件加速。
3,js优化
(1) 使用gulp、webpack等构建工具进行合并、压缩处理,以缩小js文件体积和数量
(2) 使用webpack构建时,推荐拆分成2-3个js文件进行打包,并开启压缩,防止单个js文件过大
(3) 使用webpack构建时,推荐使用tree-shaking、prepack插件优化js代码构建,缩小体积
(4) 使用innerHTML替代DOM操作,防止页面不断重复地全局渲染
(5) 使用react、vue等高性能UI构建框架,避免直接操作DOM。
(6) 使用jslint等js语法检查工具,优化js代码
4,图片资源优化
(1) 图片合并——对小图进行sprite(雪碧图)处理
(2) 图片压缩——缩小图片体积
(3) 图片大小——做图时避免单个图片过大,最好能控制在500k以内
静态资源优化推荐的工具:gulp、webpack、fis3
(三) api请求优化
api请求,也就是请求后端工程师编写的后台接口,如果请求过程中出现中断、挂起(无响应)、响应超时、响应时间过长等问题,使得客户端长时间获取不到数据,页面得不到数据填充,也会造成性能影响。
api请求优化主要从两方面入手,一是客户端做http请求异常处理,二是后端接口优化。
1,http请求异常处理
(1) 请求超时处理——timeout
当http请求超过限定的时间后中断请求,给予用户相应的提示。
(2) 错误处理
根据不同的响应错误给予用户相应的提示。
2,后端接口优化
(1) 避免无响应的情况发生
(2) 避免过度操作复杂的逻辑
(3) 避免过度的嵌套查询
(4) 与前端约定好一套响应规则,包括响应状态码、数据格式、消息提示等等
(5) 服务器开启gzip压缩、以及服务器缓存
四,其他优化
1,服务器缓存
善用缓存,只加载初始化或有更新状态的资源,对无更新状态的资源则返回已缓存的结果。
这样可实现快速响应请求、减少服务器带宽占用和资源浪费。
对于资源的更新,可对资源添加时间戳或随机字符串的形式来处理,可参考gulp、webpack版本控制实现
2,客户端缓存——cookie、WebStorage
客户端可对http请求的结果进行缓存,在数据无更新的状态下,可直接使用已缓存的结果,而不用再次发出多余的http请求。这对于一些不变或更新频率较低的数据尤为实用。
客户端缓存的方案主要有cookie、WebStorage、Application Cache。善用它们可提高你的应用的性能。
3,使用cdn存储静态资源
使用cdn服务器存储图片、文件、音频/视频等静态资源文件,这样可避免过多占用服务器带宽和服务器磁盘空间。
若配置有不同地域多节点cdn服务器,可实现就近节点传输,加快http请求速度。