衡量指标:window.performance.timing:
timeingInfo=performance.timing;
复制代码
-
页面级别优化
-
减少HTTP请求次数:
-
影响: http请求会带来时间成本和资源成本。一个完整的http请求,需要经过DNS寻址、与服务器建立连接、发送数据、等待服务器响应数据、接收数据的复杂过程;
- 时间成本:表现为用户需要看到的或者感受到的这个资源必须结束的过程;
- 资源成本:表现为每个http请求都需要携带数据,因此每个请求都需要占用带宽。由于浏览器进行并发请求的请求数是有上限的,所以,当浏览器请求数量多了以后,浏览器需要进行分批请求;从而增加用户的等待时间,给用户造成站点慢的现象;
-
途径:
-
设计实现层面简化页面: 保持页面的简洁,减少资源的使用;
-
合理设置HTTP缓存: 适当的利用缓存可以减少HTTP请求;原则是缓存越多越久越好。例如:
1、 很少变化的图片资源可以直接通过HTTP Header 中的expires 设置一个很长的过期头;
2、变化不频繁而又有可能变的资源使用Last-Modifed来做请求验证。
-
-
资源合并与压缩
- 通过webpack等打包工具;将外部JS脚本、css样式、image等合并为一个压缩文件
-
css sprites
- 合并CSS 图片,减少请求资源数量;
-
使用Inline Images ;
- 使用data:URL schema 的方式将图片嵌入到CSS中; background: url(data:image/png;base64,iVBORw0KGgoAA AANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAA....);
-
Lazy Load Images(图片懒加载): -减少首屏加载;
-
-
将外部脚本置底:
- 浏览器是可以进行并发请求的,这一特点使其能够更快的加载资源;然而,当外部脚本在加载时,会阻塞其他的资源,例如,在脚本未加载完成之前,在改脚本后面的图片资源,样式资源、其他的脚本都会处于阻塞状态,直到当前外部脚本加载完成以后,才开始执行后面资源的加载。
- 因此将外部脚本放在靠前的位置,会影响整个页面的加载速度,从而影响用户的体验;
-
异步执行inline 脚本:
- inline 脚本对性能的影响和外部脚本相比也是有过之而不及;与外部脚本一样,当inline 脚本执行的时候,一样会阻塞并发请求;由于JS在浏览器中的执行是单线程的,当页面的inline脚本在页面渲染之前执行时候,会阻塞页面的渲染;使用setTimeout()或者Web Workers 机制等;
-
Lazy Load Javascript (脚本懒加载):
- 只在需要的时候,进行加载;例子:YUI的实现中,最初只加载核心模块、其他模块等到了需要的时候进行加载;
-
将CSS放在HEAD中:
- 有些浏览器在CSS下载完成以后,才会开始渲染页面,如果CSS放在其他的地方,则可能会延迟渲染;
-
避免重复资源请求: -由于疏忽或页面由多个模块拼接而成,然后每个模块中请求了同样的资源时,会导致资源的重复请求
-
-
代码级别优化
-
DOM操作:
-
操作是脚本中最耗性能的;如增加、修改、删除 DOM元素或者对 DOM集合进行操作; 当你需要遍历 HTML Collection的时候,尽量将它转为数组后再访问,以提高性能。 即使不转换为数组,也请尽可能少的访问它,例如在遍历的时候可以将 length属性、 成员保存到局部变量后再使用局部变量。
-
避免使用 eval和 Function
- 每次 eval 或 Function 构造函数作用于字符串表示的源代码时,脚本引擎都需要将源代码转换成可执行代码。这是很消耗资源的操作 —— 通常比简单的函数调用慢 100倍以上。
- eval 函数效率特别低,由于事先无法知晓传给 eval 的字符串中的内容,eval在其上下文中解释要处理的代码,也就是说编译器无法优化上下文,因此只能有浏览器在运行时解释代码。这对性能影响很大。
- Function 构造函数比 eval略好,因为使用此代码不会影响周围代码 ;但其速度仍很慢。
- 此外,使用 eval和 Function也不利于Javascript 压缩工具执行压缩。
-
减少作用域链查找
- 作用域链查找问题,这一点在循环中是尤其需要注意的问题。如果在循环中需要访问非本作用域下的变量时请在遍历之前用局部变量缓存该变量,并在遍历结束后再重写那个变量,这一点对全局变量尤其重要,因为全局变量处于作用域链的最顶端,访问时的查找次数是最多的。
- 低效率的写法:
var count=0; function countInc(){ for(var i=0;i<1000;i++;){ count++ } }
相对高效的写法:
var count=1; function countInc(){ var temCount=count; for(var i=0;i<1000;i++ ){ tempCount++ } count=tempCount; } 复制代码
- 此外,要减少作用域链查找还应该减少闭包的使用。
-
-
数据访问
-
Javascript中的数据访问包括直接量 (字符串、正则达式 )、变量、对象属性以及数组,其中对直接量和局部变量的访问是最快的,对对象属性以及数组的访问需要更大的开销。当出现以下情况时,建议将数据放入局部变量:
- 对任何对象属性的访问超过 1次
- 对任何数组成员的访问次数超过 1次
- 还应当尽可能的减少对对象以及数组深度查找。
-
初始化页面优化:
初始化的过程中,可以对提升页面性能:
- JS优化:<script> 标签加上defer属性或者async属性,用于在不阻塞页面文档解析的前提下,控制脚本的下载和执行;
- defer属性:用户开启新的线程下载脚本文件,并使脚本在文档解析完成之后执行;
- async属性:H5新增属性,用于异步下载脚本文件,下载完毕后立即解释执行代码;
- css优化:<link>标签的ref属性中的属性值设置为preload,能够让你在你的html页面中指明哪些资源是在页面加载完成以后,立刻需要的,css资源将按顺序加载,最有的配置加载顺序,提高渲染性能;
复制代码
Issue1:什么是重绘repaint?什么是回流reflow?