加载 Javascript 最佳实践

相信很多与页面打过交道的同学都对 Yahoo 的 Best Practices for Speeding Up Your Web Site 不陌生。而这 35 条最佳实践中,对 Javascript 的加载顺序的要求是:Put Scripts at the Bottom。因为根据 看来,在同一时间加载两个文件是最理想的,而 Javascript 脚本会阻碍平行下载。Steve 说那是 2008 – 2009 那个时代用的。现在,加载 Javascript 已经有了革命性的化变。

javascript-download

在开讲之前,有一个必须解决的问题是:为什么我们要把 JS 文件放在 </body> 之前的最底部。根本原因是,它不能平行下载。而其实并不是所有浏览器都不支持。现在大部分浏览器都支持 Script 的平行下载,除了老掉牙的 IE6&7、Firefox 2&3.0、 Safari 3、Chrome 1。但我们最熟悉的老掉牙同学 IE6 (或以IE为核的那些壳)还是中国(甚至世界上)市场上占用率最高的浏览器,因此我们需要一个折衷的方案。

一、分析

我们有6种方法可以实现平行(NON-Blocking)下载:

XHR Eval – 用 XHR 下载,并 eval() 执行 responseText.。 XHR Injection – 用 XHR 下载,在页面中动态创建一个 script 元素,并将 responseText 作为其 text 。 Script in Iframe – 把脚本放在 HTML 中,使用 ifame  来下载它。 Script DOM Element – 动态创建一个 script 元素,把 src 指向脚本URL. Script Defer – 给 script 标添加 defer 属性 document.write Script Tag – 利用 document.write 把 <script src=""> 添加到 HTML 中。但这个只对 IE 有效。

兼容性可看下图:

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  
二、方案

对于究竟应该使用哪种方案。这完全取决于你需要自身的需要。这张图描述了什么时候使用什么方法:

0405-load-scripts-decision-tree-04

从总体上看来,Script DOM Element 是比较好的方案。NCZ 的博客上提过,目前最好的技术是:

创建两个 JavaScript  文件。第一个文件只提供动态下载 Javascript 的代码,第二个文件则包含所有其他页面所需脚本的文件。 像 <script> 在页部(</body> 之前)引入第一个文件。 创建第二个 <script> 来执行下载第二个 Javascript 文件的函数和其他的初始化代码。 三、实现代码

根据上面的提到的技术。NCZ 推荐第一个文件只包含相应的实现第二个文件动态加载的代码:

复制代码 代码如下:


function loadScript(url, callback){

var script = document.createElement("script")
script.type = "text/javascript";

if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" ||
script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function(){
callback();
};
}

script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}


然后,我们可以在页面中这样做:

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdjfsj.html