概要
一说到页面性能优化,可能大家都会想到很多关键词,例如:雅虎军规、2-5-8原则、3秒首屏指标等。虽说这些东西不是我们开发的硬性指标,但是在我们追求页面性能、用户体验等或者迫于良心谴责(自老板的压力),就要对我们项目开发的代码进行优化调整。
加载优化
(1)、减少http(s)请求数。
据统计,页面响应时间的80%花在图片、样式及脚本等资源的下载上,但这些又是网页渲染不可或缺的。而在这个http2还未普及的情况下,每请求一个资源就要建立一个TCP连接,就比较耗时,并且移动设备浏览器同时响应请求为4个请求(Android
支持4个,iOS5+
支持6个)。所以我们要尽量减少网而的http(s)的请求。
-
合并js和css,并压缩(webpack配置)
-
图标等小图片制作成雪碧图(精灵图)(webpack-spritesmith)
-
大图片使用图片压缩工具压缩(tinypng在线压缩)
(2)、资源缓存
使用缓存可减少向服务器的请求数,节省加载时间,所有静态资源都要在服务器端设置缓存,并且尽量使用长缓存(使用时间戳更新缓存)。
-
使用长缓存来缓存静态资源
-
使用外联js和css
(3)、减少DNS查询
用户输入URL以后,浏览器首先要查询域名(hostname)对应服务器的IP地址,一般需要耗费20-120毫秒时间。DNS查询完成之前,浏览器无法从服务器下载任何数据。
基于性能考虑,ISP、局域网、操作系统、浏览器都会有相应的DNS缓存机制。
- IE缓存30分钟,可以通过注册表中DnsCacheTimeout项设置;
- Firefox缓存1分钟,通过network.dnsCacheExpiration配置;
虽然减少不同主机名可以减少DNS查询,但是减少不同主机名数量意味着降低了浏览器并行下载资源的数量。原则上是把资源分散到2~4个不同主机名下,这是同时减少DNS查找和允许高并发下载的折中方案。
(4)、避免重定向
客户端收到服务器的重定向响应后,会根据响应头中Location的地址再次发送请求。重定向会影响用户体验,尤其是多次重定向时,用户在一段时间内看不到任何内容,只看到浏览器进度条一直在刷新。
(5)、缓存ajax请求
最重要的的优化方式是缓存响应结果。有尚未过期的Expires或者Cache-Control HTTP头,那么之前的资源就可以从缓存中读出。必须通知浏览器,应该继续使用之前缓存的资源响应,还是去请求一个新的。可以通过给资源的Ajax URL里添加一个表明用户资源最后修改时间的时间戳来实现。如果资源从上一次下载之后再没有被修改过,时间戳不变,资源就将从浏览器缓存中直接读出,从而避免一次额外的HTTP往返消耗。
(6)、按需加载
将不影响首屏的资源和当前屏幕不用的资源放到用户需要时才加载,可以大大减少请求资源的体积和数量,速度也可以显著提升。webpack懒加载。
(7)、预加载
预先加载利用浏览器空闲时间请求将来要使用的资源,以便用户访问下一页面时更快地响应。
-
在loading过渡完预加载所需资源。
-
根据用户行为的预判去预加载相关资源。
-
网页版本更新前预加载所需资源或者缓存一些用户资源。
(8)、启动gzip
前端工程师可以想办法明显地缩短通过网络传输HTTP请求和响应的时间。毫无疑问,终端用户的带宽速度,网络服务商,对等交换点的距离等等,都是开发团队所无法控制的。但还有别的能够影响响应时间的因素,压缩可以通过减少HTTP响应的大小来缩短响应时间。
Gzip压缩通常可以减少70%的响应大小,对某些文件更可能高达90%,比Deflate更高效。主流 Web 服务器都有相应模块,而且绝大多数浏览器支持gzip解码。所以,应该对HTML、CSS、JS、XML、JSON等文本类型的内容启用压缩。
注意!!! 图片和 PDF 文件不要使用 gzip。它们本身已经压缩过,再使用 gzip 压缩不仅浪费 CPU 资源,而且还可能增加文件体积。
执行优化
- css写在头部,js写在尾部并异步加载。
- 避免img、iframe等的src为空。虽然src属性为空字符串,但浏览器仍然会向服务器发起一个HTTP请求(IE 向页面所在的目录发送请求;Safari、Chrome、Firefox向页面本身发送请求;Opera不执行任何操作)。
- 尽量避免重置图像大小,多次重置图像大小会引发图像的多次重绘,影响性能。
- 图像尽量避免使用DataURL,DataUrl图像没有使用图像的压缩算法,文件会变大,并且要解码后再渲染,加载慢耗时长。
渲染优化
- 设置viewport,HTML的
viewport
可加速页面的渲
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, minimum-scale=1, maximum-scale=1">
- 减少DOM节点,DOM节点太多影响会影响dom树构建,进而影响渲染树构建。
- 优化动画
- 尽量使用CSS3动画
- 合理使用requestAnimationFrame动画代替setTimeout
- 适当使用Canvas动画:5个元素以内使用
CSS动画
,5个元素以上使用Canvas动画
,iOS8+
可使用WebGL动画
- 优化高频事件,
scroll
、touchmove
等事件可导致多次渲染
- 函数节流
- 函数防抖
- 使用requestAnimationFrame监听帧变化:使得在正确的时间进行渲染
- 增加响应变化的时间间隔:减少重绘次数
- GPU加速:使用某些HTML5标签和CSS3属性会触发
GPU渲染
,请合理使用(过渡使用会引发手机耗电量增加)
- HTML标签:
video
、canvas
、webgl
- CSS属性:
opacity
、transform
、transition
样式优化
- 避免css表达式,CSS表达式超出预期的频繁执行,页面滚动、鼠标移动时都会不断执行,带来很大的性能损耗。
- 移除css空规则,CSS空规则增加了css文件的大小,影响CSS树的执行。
- 正确使用display,
display
会影响页面的渲染
display:inline
后不应该再使用float
、margin
、padding
、width
和height
display:inline-block
后不应该再使用float
display:block
后不应该再使用vertical-align
display:table-*
后不应该再使用float
和margin
- 不滥用float,float在渲染时计算量比较大,尽量减少使用
- 不滥用wen字体,Web字体需要下载、解析、重绘当前页面,尽量减少使用
- 不声明过多的font-size,过多的font-size影响css树的构建效率
- 值为0时不设置单位,为了浏览器兼容性和性能,值为0时不要带单位。
- 标准化各种浏览器前缀
- 无前缀属性应放在最后
- CSS动画属性只用-webkit-、无前缀两种
- 其它前缀为-webkit-、-moz-、-ms-、无前缀四种:
Opera
改用blink
内核,-o-
已淘汰
- 不要使用 filter,
AlphaImageLoader为IE5.5-IE8专有的技术,和CSS表达式一样,放进博物馆吧。IE专有的AlphaImageLoader滤镜可以用来修复IE7之前的版本中半透明PNG图片的问题。在图片加载过程中,这个滤镜会阻塞渲染,卡住浏览器,还会增加内存消耗而且是被应用到每个元素的,而不是每个图片,所以会存在一大堆问题。注意!!!这里所说的不是 CSS3 Filter
脚本优化
- 减少重绘和回流
- 减少dom操作
- 避免使用document.write
- 尽量改变class而不是style,使用classList代替className
- 避免dom元素批量绑定事件,尝试事件委托
- 尽量使用id选择器:
id
选择器选择元素是最快的 - touch事件优化:使用
tap
(touchstart
和touchend
)代替click
(注意touch
响应过快,易引发误操作) - 避免js递归操作(可用尾递归或循环方式代替)
- 避免使用闭包