对于html的script标签,如果是外链的情况,如:
<script src="a.js"></script>
浏览器对它的处理主要有2部分:下载和执行
下载在有些浏览器中是并行的,有些浏览器中是串行的,如IE8、Firefox3、Chrome2都是串行下载的
执行在所有浏览器中默认都是阻塞的,当js在执行时不会进行html解析等其它操作,所以页面顶部的js不宜过大,因为那样将导致页面长时间空白,对于这些外链js,有2个属性可以减少它们对页面加载的影响,分别是:
- async
- 标识js是否异步执行,当有这个属性时则不阻塞当前页面的加载,并在js下载完后立刻执行
- 不能保证多个script标签的执行顺序
- defer
- 标示js是否延迟执行,当有这个属性时js的执行会推迟到页面解析完成之后
- 可以保证多个script标签的执行顺序
下图来自Asynchronous and deferred JavaScript execution explained,清晰地解释了普通情况和这2种情况下的区别
![](https://img-blog.csdn.net/20130516092151815)
需要注意的是这两个属性目前对于内嵌的js是无效的
而对于dom中创建的script标签在浏览器中则是异步的,如下所示:
var script = document.createElement('script');
script.src = 'a.js';
document.getElementsByTagName('head')[0].appendChild(script);
为了解决js阻塞页面的问题,可以利用浏览器不认识的属性来先下载js后再执行,如ControlJS就是这样做的,它能提高页面的相应速度,不过需要注意处理在js未加载完时的显示效果
document.write
document.write是不推荐的api,对于标示有async或defer属性的script标签,使用它会导致不可预料的结果,除此之外还有以下场景是不应该使用它的:
- 使用document.createElement创建的script
- 事件触发的函数中,如onclick
- setTimeout/setInterval
简单来说,document.write只适合用在外链的script标签中,它最常见的场景是在广告中,由于广告可能包含大量html,这时需要注意标签的闭合,如果写入的内容很多,为了避免受到页面的影响,可以使用类似Google AdSense的方式,通过创建iframe来放置广告,这样做还能减少广告中的js执行对当前页面性能的影响
另外,可以使用ADsafe等方案来保证嵌入第三方广告的安全,请参考如何安全地嵌入第三方js – FBML/caja/sandbox/ADsafe简介
script标签放底部
将script标签放底部可以提高页面展现给用户的速度,然而很多时候事情并没那么简单,如页面中的有些功能是依赖js的,所以更多的还需要根据实际需求进行调整
- 尝试用Doloto分析出哪些JS和初始展现是无关的,将那些不必要的js延迟加载
- 手工进行分离,如可以先显示出按钮,但状态是不可点,等JS加载完成后再改成可点的
传输
js压缩可以使用YUI Compressor或Closure Compiler
gwt中的js压缩还针对gzip进行了优化,进一步减小传输的体积,具体请阅读On Reducing the Size of Compressed Javascript
css
比起js放底部,css放页面顶部就比较容易做到
@import
使用@import在IE下会由于css加载延后而导致页面展现比使用link标签慢,不过目前几乎没有人使用@import,所以问题不大,具体细节请参考don’t use @import
selector的优化
浏览器在构建DOM树的过程中会同时构建Render树,我们可以简单的认为浏览器在遇到每一个DOM节点时,都会遍历所有selector来判断这个节点会被哪些selector影响到
不过实际上浏览器一般是从右至左来判断selector是否命中的,对于ID、Class、Tag、Universal和Page的规则是通过hashmap的方式来查找的,它们并不会遍历所有selector,所以selector越精确越好,google page-speed中的一篇文档Use efficient CSS selectors详细说明了如何优化selector的写法
另一个比较好的方法是从架构层面进行优化,将页面不同部分的模块和样式绑定,通过不同组合的方式来生成页面,避免后续页面顶部的css只增不减,越来越复杂和混乱的问题,可以参考Facebook的静态文件管理
工具
以下整理一些性能优化相关的工具及方法
Browserscope
之前提到的http://www.browserscope.org收集了各种浏览器参数的对比,如最大链接数等信息,方便参考
Navigation Timing
Navigation Timing是还在草案中的获取页面性能数据api,能方便页面进行性能优化的分析
传统的页面分析方法是通过JavaScript的时间来计算,无法获取页面在网络及渲染上所花的时间,使用Navigation Timing就能很好地解决这个问题,具体它能取到哪些数据可以通过下图了解(来自w3c)
![](https://img-blog.csdn.net/20130516092205447)
目前这个api较新,目前只在一些比较新的浏览器上有支持,如Chrome、IE9,但也占用一定的市场份额了,可以现在就用起来
boomerang
yahoo开源的一个页面性能检测工具,它的原理是通过监听页面的onbeforeunload事件,然后设置一个cookie,并在另一个页面中设置onload事件,如果cookie中有设置且和页面的refer保持一致,则通过这两个事件的事件来衡量当前页面的加载时间
另外就是通过静态图片来衡量带宽和网络延迟,具体可以看boomerang
检测工具
reference