法则6:把script放到页面的下端
通常情况下IE与Firefox都遵循了HTTP/1.1规范关于同一个域名每次只能有两个并行下载请求的建议。如果想扩展IE的下载束缚,可以参 考:微软网站的文章:How to configure Internet Explorer to have more than two download sessions,"
http://support.microsoft.com/?kbid=282402.
IE和Firefox都会先下载host1和host2的图片,然后开始下载host1上的script,直到这个script下载完成,才会开始下载后面的两个图片。
第五章我们将样式表放置于HTML的HEAD中以加快页面渲染。其实script也有类似的问题,但解决的方法正好相反:把script放到页面的下端,会利于页面的快速渲染。
Script所带来的问题
为了更好的说明这第6条法则,我们先看一个反例吧。把script放在HTML页面的中间位置,看看这种方式页面的下载情况,如:
http://stevesouders.com/hpws/js-middle.php
这个script是睡眠10秒钟然后启动,我们访问一下这个页面,发现整个HTML已经全部download完毕,但页面在渲染到中间时, 停住了,下一半仍是空白的未渲染区域。直到这个js睡眠的10秒过后,另一半页面的内容才开始渲染和下载后面所需的图片等组件。很显然,这个放在HTML 中间的script阻碍了后面页面元素的下载,还阻碍了页面的渲染。
这也就是为什么我们要把所有的样式表放到HTML页面的上端HEAD处,它们才会被先下载,不会阻塞页面的渲染。而script后面的页面内容则会等待script执行完毕,才开始渲染。所以把script放置的越下,更多的页面内容才会更快的渲染。
并行下载
对下载速度影响最大的就是页面组件的数量。前几章介绍过,如果当前浏览器的缓存是空的,则每一个组件都产生一个HTTP请求。你可能会问:那为什么浏览器不一次性的请求所有的组件呢,非得一个一个的去请求?
要解释这个,就要说到HTTP/1.1规范了,它建议 浏览器一次对同一个域名最多只发起2个并行下载请求.( http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.4)
要解释这个,就要说到HTTP/1.1规范了,它建议 浏览器一次对同一个域名最多只发起2个并行下载请求.( http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.4)
很多的页面连同其所包含的组件都是一个域名下的,如下图所示的组件下载的阶梯图 6-1:

如果一个页面的组件是分布在两个域名下的,那它的响应时间总体来说应该会快两倍,如图6-2所示的情况,会有四个组件并行下载。

而要改Firefox的默认设置,则可以在配置页面中修改network.http.maxpersistent- connections-per-server属性.有意思的是,在对HTTP/1.0的支持中,Firefox默认的是每个域名下同时可有八个并行下载 请求,也就是说可一次同时下载8个页面组件,这可比IE的默认值要大方多了。如图6-3就是显示的在Firefox下下载一个页面的示意图,这可要比 6-2所示的看起来爽多了。

现在大多数的网站都遵循HTTP/1.1规范,增加每个域名下的并行下载数量是个办法,但我们总不能都指望着用户去调整自己浏览器的设置参数。
前端工程师应该考虑把页面组件放在不同的域名下,增加并行下载最多也只是消耗一点客户端的CPU资源和带宽,除非是大量的并行下载才会影响到性能。在Yahoo!的实验下,
我们发现把页面组件放在两个域名下要比划分成1,4或10个域名性能要好,具体可参见(Tenni Theurer, "Performance Research, Part 4: Maximizing Parallel Downloads in the Carpool Lane,"
http://yuiblog.com/blog/2007/04/11/performance-research-part-4/.)
Script是怎么阻碍下载的
组件并行下载的好处我们都知道了。但script这个东西却可能会破坏这个和谐社会:因为script可能会用document.write语句来改变页面内容,所以浏览器会等待script执行完毕。
另一个原因是浏览器要保证script的执行顺序,先出现的script要先执行,哪怕后面的script的k数有多么小,也要等着,因为script在功能上可能会有前后关系,后面的script可能会用到前面script的某些操作。
另一个原因是浏览器要保证script的执行顺序,先出现的script要先执行,哪怕后面的script的k数有多么小,也要等着,因为script在功能上可能会有前后关系,后面的script可能会用到前面script的某些操作。
来个例子说明
http://stevesouders.com/hpws/js-blocking.php
这个页面所包含的组件出现顺序如下:
1,host1下的图片A1
2,host2下的图片B1
3,host1下的script,等待10秒完成
4,host1下的图片A2
5,host2下的图片B2
看看是host1下的两张图片同时下载?还是其他?
http://stevesouders.com/hpws/js-blocking.php
这个页面所包含的组件出现顺序如下:
1,host1下的图片A1
2,host2下的图片B1
3,host1下的script,等待10秒完成
4,host1下的图片A2
5,host2下的图片B2
看看是host1下的两张图片同时下载?还是其他?

最糟糕的情况:script在页面的顶部
在这种情况下将会导致页面是个空白:
• Script下的文字页面内容会被阻止渲染。
• Script下的组件也会被阻止下载
• Script下的组件也会被阻止下载
直到这个script下载并执行完毕才会解除阻止。给个实例:
http://stevesouders.com/hpws/js-top.php
因为script在顶部,整个页面的渲染被阻止了,于是这个页面将会呈现一个我们在第五章中解释的空白屏。而逐步渲染是一个很关键的良好用户体验。图6-5就是这个例子的页面下载阶梯图,后面的图片组件都被阻止了。
因为script在顶部,整个页面的渲染被阻止了,于是这个页面将会呈现一个我们在第五章中解释的空白屏。而逐步渲染是一个很关键的良好用户体验。图6-5就是这个例子的页面下载阶梯图,后面的图片组件都被阻止了。

最好的情况:script在页面的底部
放置script最佳的地方当然是页面的底部了。页面的内容不会被阻止渲染,可视组件能依次下载渲染。如实例
http://stevesouders.com/hpws/js-bottom.php,图6-6就显示了这种方式script对页面的影响是最小的,我们可以对比一下图6-5看看,再给一个具体的比较实例吧:
http://stevesouders.com/hpws/move-scripts.php是不是感觉更明显了。

这也不是说所有的scrript就应该放到页面底部了,如果是包含有document.write这样影响页面渲染内容的script,是 不应该被放到最下面的,所以还是要以实际的页面功能、逻辑等方面来考虑,通常情况下,只要是不涉及强制更改页面渲染的js,都应该放到页面底部。
另外有一种方式是
http://stevesouders.com/hpws/js-defer.php所示的defer方式,在script定义时声明,但这种只对IE有效,对firefox无效,大家知道一下就行了。