相信很多与页面打过交道的同学都对 Yahoo 的 [url=http://developer.yahoo.com/performance/rules.html]Best Practices for Speeding Up Your Web Site[/url] 不陌生。而这 35 条最佳实践中,对 Javascript 的加载顺序的要求是:Put Scripts at the Bottom。因为根据 [url=http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.4]HTTP/1.1 specification[/url] 看来,在同一时间加载两个文件是最理想的,而 Javascript 脚本会阻碍平行下载。Steve 说那是 2008 – 2009 那个时代用的。现在,加载 Javascript 已经有了革命性的化变。
[img]http://files.jb51.net/upload/201110/20111030233635188.png[/img]
在开讲之前,有一个必须解决的问题是:为什么我们要把 JS 文件放在
</body> 之前的最底部。根本原因是,它不能平行下载。而其实并不是所有浏览器都不支持。现在大部分浏览器都支持 Script 的平行下载,除了老掉牙的 IE6&7、Firefox 2&3.0、 Safari 3、Chrome 1。但我们最熟悉的老掉牙同学 IE6 (或以IE为核的那些壳)还是中国(甚至世界上)市场上占用率最高的浏览器,因此我们需要一个折衷的方案。
[h2]一、分析[/h2]
我们有6种方法可以实现平行(NON-Blocking)下载:
[list]
[*][b]XHR Eval[/b] – 用 XHR 下载,并 [code]eval()[/code] 执行 responseText.。
[/*][*][b]XHR Injection[/b] – 用 XHR 下载,在页面中动态创建一个
script 元素,并将 responseText 作为其
text 。
[/*][*][b]Script in Iframe[/b] – 把脚本放在 HTML 中,使用 ifame 来下载它。
[/*][*][b]Script DOM Element[/b] – 动态创建一个
script 元素,把 [code]src[/code] 指向脚本URL.
[/*][*][b]Script Defer[/b] – 给
script 标添加 [code]defer[/code] 属性
[/*][*][b][code]document.write[/code] Script Tag[/b] – 利用 [code]document.write [/code]把 [code]<script src="">[/code] 添加到 HTML 中。但这个只对 IE 有效。 [/*][/list]
兼容性可看下图:
| Technique |
Parallel Downloads |
Differ |
Existing Scripts |
Busy Indicators |
Ensures Order |
Size (bytes) |
| XHR Eval |
IE, FF, Saf, Chr, Op |
no |
no |
Saf, Chr |
- |
~500 |
| XHR Injection |
IE, FF, Saf, Chr, Op |
no |
yes |
Saf, Chr |
- |
~500 |
| Script in Iframe |
IE, FF, Saf, Chr, Op |
no |
no |
IE, FF, Saf, Chr |
- |
~50 |
| Script DOM Element |
IE, FF, Saf, Chr, Op |
yes |
yes |
FF, Saf, Chr |
FF, Op |
~200 |
| Script Defer |
IE, Saf4, Chr2, FF3.1 |
yes |
yes |
IE, FF, Saf, Chr, Op |
IE, FF, Saf, Chr, Op |
~50 |
| document.write Script Tag |
IE, Saf4, Chr2, Op |
yes |
yes |
IE, FF, Saf, Chr, Op |
IE, FF, Saf, Chr, Op |
~100 |
[h2]二、方案[/h2]
对于究竟应该使用哪种方案。这完全取决于你需要自身的需要。这张图描述了什么时候使用什么方法:
[url=http://www.1sucai.cn/upload/201110/20111030233635223.gif][img]http://files.jb51.net/upload/201110/20111030233635223.gif[/img]
[/url]
从总体上看来,Script DOM Element 是比较好的方案。NCZ 的博客上提过,目前最好的技术是:
[list=1]
[*]创建两个 JavaScript 文件。第一个文件只提供动态下载 Javascript 的代码,第二个文件则包含所有其他页面所需脚本的文件。
[/*][*]像 [code]<script>[/code] 在页部(
</body> 之前)引入第一个文件。
[/*][*][code]
创建第二个 <script>[/code] 来执行下载第二个 Javascript 文件的函数和其他的初始化代码。 [/*][/list]
[h2]三、实现代码[/h2]
根据上面的提到的技术。NCZ 推荐第一个文件只包含相应的实现第二个文件动态加载的代码:
[url=http://www.stevesouders.com/blog/2009/04/27/loading-scripts-without-blocking/]Loading Scripts Without Blocking[/url]
[*][url=http://www.nczonline.net/blog/2009/07/28/the-best-way-to-load-external-javascript/]The best way to load external JavaScript[/url]
[/*][*][url=http://www.stevesouders.com/blog/2010/12/06/evolution-of-script-loading/]Evolution of Script Loading[/url]
[/*][*][url=http://www.nczonline.net/blog/2010/08/10/what-is-a-non-blocking-script/]What is a non-blocking script?[/url]
[/*][*][url=http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#attr-script-async]HTML5 – Scripting: async Attribute[/url] [/*][/list]