内联脚本的位置对性能的影响
原文
Steve Souders: Positioning Inline Scripts. 好文无需废话,推荐仔细阅读。
测试
值得注意的一个结论:
要避免将内联脚本放在样式表和页面其它资源之间,这非常重要。这会使得看起来像是样式表阻塞了后续资源的下载。这种行为的原因是:所有主流浏览器都会保持CSS和JavaScript的顺序。在样式表完全下载、解析及应用之后,内联脚本才能执行。同时,必须在内联脚本执行后,剩余资源才能下载。这就使得,放在样式表和内联脚本之后的资源,下载被阻塞了。
内联脚本放在样式表之前,样式表和脚本的下载是并发的:

测试页面A:inline_script_position_test1.html
内联脚本放在样式表之后,会导致后续资源的下载被阻塞:

测试页面B:inline_script_position_test2.html
页面A和页面B的唯一区别就是,内联脚本的位置放在样式表前面,但就这么简单的一个位置调整,能节省约100ms下载时间。
实战
来看淘宝网首页的源代码片段:

第15行的内联脚本,放在第11行的样式表后面,直接导致了下面这张timeline:

在tbsp.css没下载完之前,所有资源的下载都阻塞掉了!
仅要将第15行的内联脚本放到样式表前面,立刻就能提速100多ms.(注:淘宝首页正在做性能优化,这个调整将很快实施)
目前eBay, Amazon等大型站点的首页也存在此问题。国内站点看了下有啊和拍拍。有啊的都外链,没问题(感叹百度的硬件,不在乎多几个HTTP链接数)。拍拍的则都内联,因此也没问题(看完有啊看拍拍,有点怪怪的,说不出来的感觉)。
结尾
页面编码时,在head里,习惯性先写style再写script. 以后遇上inline script时,还是得调整下位置,放到style前面去。

May 24th, 2009 on 22:43
好文,好沙发。另外说下本文的代码74行好像少了
May 24th, 2009 on 22:48
哦?改过来了好像。还是我刚刚看错了。囧
May 24th, 2009 on 22:50
每次读你的博文都有收获。
May 24th, 2009 on 22:53
@wlsy: 我刚修改的,感谢你的及时反馈^o^
May 24th, 2009 on 22:59
我之前测试过了,只有FF是这样处理的,其他的主流浏览器已经没有这个问题。
May 24th, 2009 on 23:03
如果有内联脚本,我一直是样式表最后的。看来这个习惯非常不科学。
May 25th, 2009 on 0:04
inline放到style之前。以前都没注意
May 25th, 2009 on 8:11
@xiaoma: 我昨天也测了,感觉是其它浏览器下的timeline有问题,比如fiddler的timeline,和safari的time. 在无缓存情况下,内联脚本放在样式表后面,在所有浏览器中都会导致加载的时间更长。
May 25th, 2009 on 8:41
那么,如果我将内联js放入页脚呢?效率不会提高?
May 25th, 2009 on 9:10
如果这样的话,就有个问题啊。比如一般我们都会把外联JS脚本放在前面,比如一个jquery.js。但要写部分内联JS代码,这样放到前调用JQ应该就有问题了
May 25th, 2009 on 9:13
你这两个测试代码我在IE8下测试好几次都是第二个要快些。不知道为什么
May 25th, 2009 on 10:02
同样是习惯性的把JS放在CSS后面,呵呵,看过之后一定改。但在我看来并不是把所有东西都放到HTML页面上就好,像基本样式、JS等我更愿意单独存放,因为这些只是在第一次浏览时才会加载,相信绝大部分使用者都是开启缓存的,这样之后这两个基本的文件就不用现次加载,所省下来的应该是更大的部分,尤其像淘宝这种访问页面数目相当大的网站就更是能起到明显的效果。
May 25th, 2009 on 10:59
淘宝把JS放到HTML是有他们的考虑的,以前在JAVAEYE上看他们讲过
May 25th, 2009 on 11:23
@jejwe:IE8的问题,你有没有清缓存?
May 25th, 2009 on 11:50
我在 Chromium 3 上测试,第二个总是比第一个快。
Anyway, 考虑到浏览器差异,以及阻塞时间并不是很长,个人认为这个问题基本上可以忽略。如果考虑到大部分用户都是 IE, 我会选择 IE 下 load 更快的方案。
May 25th, 2009 on 12:52
但是yslow 里面是介绍让脚本放到页面最后的,这是为什么呢?
May 25th, 2009 on 21:36
学习了
May 26th, 2009 on 9:50
文章很不错,以前一直没注意这个问题。
May 26th, 2009 on 14:24
我测试了几次,似乎数据不太一样。
ff3
Case: inline script before style link
page load time: 2956 ms
Case: inline script after style link
page load time: 2252 ms
ie7相反
Case: inline script before style link
page load time: 2016 ms
Case: inline script after style link
page load time: 2313 ms
经过多次清楚缓存,多次打开测试。
May 27th, 2009 on 10:49
感谢射雕同学。经常从TB楼下走过。。。。TB就是经常加班,噢
May 27th, 2009 on 21:39
IE7下多次测试,清不清缓存都试过,总是第2个快…
May 28th, 2009 on 9:08
好文,绝对的好文!
不得不站出来~
May 28th, 2009 on 14:08
IE6下测试:样式表和脚本的下载不是并发的。
ff3下测试:样式表和脚本的下载是并发的。
可能由于网络原因,并没有显示出并发的优势。
还有这样个问题,虽然并发了,但下载速度会不会比分开下载要慢呢。
顺便提点意见,希望留言能支持贴图
May 29th, 2009 on 14:36
我觉得此处“内联脚本”应为“内部脚本”。
内联:
内部: …
外部 和 外联 好像为同一个意思。
参考:《HTML与CSS入门经典》12.5 内部样式与内联样式
http://book.csdn.net/bookfiles/283/10028312304.shtml
May 30th, 2009 on 9:11
测试页面中,第2个总是比第一个快
June 1st, 2009 on 9:59
我想内联脚本要优先运行是为了防止其对document及子对象进行操作影响到页面呈现的一致性。建议翻一下《高性能网站建设指南》P50:规则6 将脚本放在底部。
又或者看一下这篇文章:http://www.quirksmode.org/js/placejs.html
从精品逛过来的,有空联系下。
June 5th, 2009 on 12:57
高性能网站建设指南 应该更新了,还是看原版吧:
http://developer.yahoo.com/performance/rules.html
照这个,没错
June 9th, 2009 on 11:13
讨论几个问题,欢迎楼主回复。
1.你说的内联脚本只是头部的内联吧,一般在页面中也会有很多内联的脚本,我远程测试了你的两个页面,区别不大。
2.理论上将解析内联是会阻塞资源下载。我觉得对body的内联脚本做调整性能提升应该比较快。测试老外的例子感觉效果很明显。
June 21st, 2009 on 1:42
淘宝首页样式很多都是脚本、样式都写在页面中,这个方式可能是为了减少http请求造成的压力 我没有对你上面的例子进行测试,就算所有浏览器都是这样处理,那问题也来了。
到底是增加服务器的压力还是延长用户的等待时间?请求到本地的文件大小并没有多少改变,只是对于用户来说可能能早一点的看到页面而已 (这也许就是服务器压力与用户体验的一个矛盾点吧)
新浪首页里面也是有外链脚本与页面脚本,用httpWatch抓到27个js请求 没有发现请求css,感觉很奇怪 首页代码有5725行,从14行到731行全部都是样式
qq 首页也只是语法了一个换肤的样式skin1.css,其它的样式全部在页面中 脚本总共9个,不过页面脚本很多。
它们这种方式是否算是回避了你说的“内联脚本对性能的影响”?
leave a reply