网站性能,javascript性能相关知识点

1、高性能网站

《高性能网站建设指南》一书中提出用户只有10%-20%最终用户响应时间是花在从web服务器获取html文档并传送到浏览器中,80%的时间都花在了等待页面组件中,由此提出了构建高性能网站的14个规则。按照优先级排序依次是:javascript

1.减小http请求数css

直接方法是减小组件的个数,由此来减小http请求数量,能够采用的方法包括图片地图,css sprites(利用css的background-position属性,能够讲html元素放置到背景图片中指望的位置上),样式表的合并等等。html

2.使用内容发布网络CDNjava

CDN用于发布静态内容,包括图片,脚本,样式表,和flash。node

3.添加expires头web

条件GET请求和304响应有助于让页面加载得更快,然而仍然须要在客户端和服务器进行一次往返确认。expries头部经过明确指出浏览器是否可使用组件的缓存副原本消除这个须要。经过服务器会返回一个expires头。expires:thu 15.。。当浏览器看到响应有一个expries头时,它会和响应的组件一块儿保存在缓存中,只要组件没有过时,就不会发生任何http请求。ajax

长久的expries头部应该包含任何不常常变化的组件,包括脚本,样式表和flash组件。这一般是在服务器的配置文件中配置。与之相似的另外一个http头部是cache-control:max-age.若是两者同时出现,http规范规定max-age指令将重写expire头。chrome

若是确保用户能获取最新的组件,最有效的解决方案是修改器全部连接。所以为全部组件的命名最好采用变量。apache

4.压缩组件编程

客户端经过appect-encoding:gzip,deflate来表示对压缩的支持,html,文档,样式表一般是值得压缩的。图片和pdf不该该压缩,由于它们原本就已经压缩了,试图再次压缩不只浪费CPU资源,还可能会增长文件大小。

服务器端在apache的配置文件中进行配置。

5.将样式表放在顶部

将样式表放在底部会致使在浏览器中阻止内容逐步呈现,出现白屏或者FOUC(无样式内容闪烁,即内容呈现后,待样式表加载完成再次重绘)。

6.将脚本放在底部或者采用无阻塞脚本

通常,http规范建议每一个主机名能够并行下载两个组件(注意,仅仅是建议)。可是在下载脚本时,并行下载是被禁用的,页面的下载和与渲染都必须停下来等待脚本下载和执行完成。这一方面是为了保证脚本的正确执行顺序,另外一方面是为了防止document.write修改页面。所以最好将样式表放在底部。

此外,能够采用无阻塞脚本(在页面加载完成以后才加载javascript代码,意味着在DOMContentLoaded事件,或者window的load事件触发后再下载脚本,此时脚本能够放在页面任何位置)的方法有:

1)延迟的脚本

为script标签添加defer或者async属性,用于异步加载脚本。两者的相同点是采用并行加载,在下载过程当中不会产生阻塞。不一样点在于执行时机,async是加载完成后自动执行,而defer须要等到页面加载完成才执行。

2)动态脚本元素

var script=document.createElement('script');
script.type='type/javascript';
script.src='file1.js';
document.getElementsByTagName('head')[0].append('script');

动态脚本可用来实现jsonP。此外,也能够实现脚本的无阻塞加载。文件在元素被添加到页面时开始下载。不管什么时候启动下载,文件的下载和执行均不会阻塞页面其余进程。使用动态脚本节点下载文件时,返回的代码一般会当即执行。若是加载多个动态脚本,只有firefox和opera会保证脚本按照指定的顺序执行,其余浏览器则会按照服务器返回的顺序下载和执行。

动态脚本加载凭借其跨浏览器的优点,成为最通用的无阻塞加载的解决方案。使用这种方法须要两步骤:先添加动态加载所须要的代码,而后加载初始化页面所须要的其余脚本。下面是一个经过的无阻塞加载的方法:

function loadScript(url,callback){
    var script=document.createElement('script');    
    script.type='type/javascript';
    script.src=url;
    if(script.readyState){//IE
        script.onreadystatechange=function(){
            if(script.readyState==='loaded'||script.readyState==='complete'){
                script.readyState=null;
                callback();
            }
        }
    }else{
        script.onload=function(){
            callback();
        }
    }
    document.getElementsByTagName('head')[0].appendChild(script);
}

7.避免CSS表达式

这个通常都不会这么作了,所以不展开详细说明了。

8.使用外部javascript和css

使用外部文件,可缓存,可重用。

9,减小DNS查找,

经过keep-alive和较少的域名来减小DNS查找。浏览器有DNS的缓存,操做系统也有DNS的缓存,减小惟一主机名会减小DNS查找次数,但同时也减小了页面中并行下载的数量,所以建议将组件分别放到至少2个,至多4个主机名下,达到两者的权衡。

10.精简javscript

方法有两种:压缩(去除空白等),混淆(使用更短的变量、函数名)

11.避免重定向

http状态码如301,302表明重定向,304不是真正的重定向,只是响应条件GET请求,避免下载已经存在在缓存中的数据。一种重定向最为浪费,发生在URL结尾必须出现/却没有出现的时候(容许自动索引到index.html的状况下),注意主机名后面缺乏斜线并不会引发重定向。如www.baidu.com

重定向延迟了整个html文档的传输,在html文档到达以前,页面不会呈现任何东西,也没有任何组件被下载。

12.删除重复脚本

引入脚本模块化管理,防止同一个脚本屡次引入。

13.配置ETag

若是缓存的组件到期了(或者用户refresh或者reload了页面),浏览器会发送一个条件GET请求,若是浏览器检测到缓存的组件是有效的,原始服务器不会返回整个组件,而是返回一个304码。

服务器检测缓存的组件是否和原始服务器的组件匹配时有两种方式:

1)比较最新修改日期

条件get请求的请求头包含IF-MODIFED-SINCE头部,响应头包含LAST-MODIFED头部,经过比较来判断

2)实体标签ETAG

ETAG提供了另一种方式,用于检测浏览器缓存中的组件与原始服务器的组件是否匹配(实体是组件的另外一种称呼)。这种方式的http 条件GET请求会返回一个ETAG头部。

ETAG提供了另一种方式,ETAG一般基于实体的某些属性来构造,实体的状态能够反映在ETAG中,对于特定的,寄宿了网站的服务器来讲是惟一的。Apache中ETAG的格式是innode-size-timestamp,文件系统采用innode来存储诸如文件类型,全部者等信息。所以ETAG的问题是,当从一台服务器获取了原始组件,当向另外一台服务器发送条件GET请求时,ETAG是不会匹配的,这对于集群服务器来讲很常见。所以最好服务器移除或者配置默认的ETAG。

14.使ajax请求结果可缓存

2、高性能javascript

回到javascript自身的性能问题,很赞同《你不知道的javascript(中卷)》中的一句话,不要沉迷于微性能的调优,好比a++和++a。应该关注优化的大局,即代码是否运行在关键路径上。所谓关键路径,好比用户会注意到的UX关键位置,如动画循环或css风格更新,或者一段会运行屡次的“热”代码等。

1.数据访问

访问字面量和局部变量速度最快,访问数组元素和对象成员相对较慢。局部变量存在做用域链其实位置,所以最快,全局变量最慢。所以能够把经常使用的对象成员,数组元素,跨域变量保存在局部变量中来该删javascript性能。

2.DOM编程

  2.1DOM模型

文档对象模型(DOM)是一个独立于语言的,用于操做XML和HTML文档的程序接口(API)。尽管DOM是个和语言无关的API,可是它在浏览器中的接口是javascrcipt实现的。浏览器一般会把DOM和javascript(这里指ECMAscript)独立实现,好比chrome使用Webkit来渲染页面,但javascript引擎则是他们本身开发的,命名为V8.所以DOM编程中一个通用的作法是,尽可能减小DOM访问次数,把运算尽可能留在ECMAscript这一端。

  2.2HTML集合

html集合是包含了DOM节点引用的类数组对象,如下方法返回的就是html集合:

 

document.getElementsByTagName
document.getElementsByClassName
document.getElementsByName

 

此外,如下属性也一样返回html集合:

document.images
document.links
document.forms
document.forms[0].elements

html集合是类数组的列表,它们并非真的数组,不具备数组的push,slice等方法,可是具备length属性,也可使用数字下标访问元素。

根据DOM标准的定义,html集合一直和文档保持联系,文档更新时,他们也会自动更新,这意味着,每次须要最新的信息时,都会重复执行查询的过程,哪怕只是获取集合中的元素个数(即length属性),也是如此,这就形成了低效之源。例如,下面的代码会陷入死循环:

 

var allDivs=document.getElementsByTagName('div');
for(var i=0;i<allDivs.length;i++){
  document.body.appendChild(document.createElement('div'));  
}

 

此时建议将集合的长度缓存到一个变量中,若是常常操做集合,能够将它拷贝到一个数组中。

  2.3重绘与重排

javascript在下载完全部组件(html,js,css,图片)后会生成两个内部的数据结构:DOM树(表示页面结构),渲染树(表示DOM节点如何展现)。

当DOM变化影响了元素的几何属性时(宽和高)时,浏览器会使得渲染树中受到影响的部分失效,就会发生重排。重排以后,会将受影响的部分从新绘制到屏幕中,称为重绘。若是没有影响几何属性,如仅仅改变了背景色,那么只会发生重绘。

重排和重绘代价可能很是昂贵,所以要尽可能减小其次数。当须要对DOM元素进行一系列操做时,可采用如下步骤:

1).使元素脱离文档流。

脱离文档的方法有如下几种:

  A. 隐藏元素,应用修改,从新显示;

  B.使用文档片断,在当前DOM以外构建一棵子树,再把它拷贝到文档中。

  C.使用绝对定位,好比对动画元素使用绝对定位,当动画结束时恢复定位。  

2).对其应用多重改变。

3).将元素带回文档。

 

3.快速响应的用户界面

用于执行javascript和更新用户界面的进程一般被称为“浏览器UI线程”。

通常浏览器会限制javascript任务的运行时间,有的浏览器采用调用栈大小限制(好比500万条语句),有的采用长时间限制(好比100ms)。当遭遇这种状况时,考虑的解决方法有两种:

1)分时函数和延迟函数

 参见以前博客:http://www.cnblogs.com/bobodeboke/p/5594647.html

2)web workers,这是js新引入的特性,每一个work在一个独立线程中执行,不会形成阻塞。可是web workers直接访问DOM会出现错误,所以适用于解决数据计算,解析等费时的操做。

相关文章
相关标签/搜索