代码改变世界

脚本加载技术

2013-03-30 15:15  king0222  阅读(169)  评论(0编辑  收藏  举报

脚本加载技术

我们常常在网页中用行内脚本或外部脚本的形式将javascript包含在里面。但是,对于外部脚本而言,当浏览器开始下载外部脚本的时候,在脚本下载,解析并执行完毕之前,浏览器不会下载任何其他的内容。浏览器出现这种阻塞现象的原因在于,脚本可能会改变页面或者javascript的名字空间,他们会对后续内容造成影响。

我们当然希望脚本能够按需执行,但没有必要按顺序下载。为此就出现了几种能够并行加载脚本的技术。

一。XHR Eval

该技术的实现原理就是通过ajax技术获取脚本代码,并通过eval去执行它,但是这种方式的缺陷是外部脚本必须部署在同一域中。其实现代码如下:

 1 var xhrObj=getXHRObject();
 2 
 3 xhrobj.onreadystatechange=function(){
 4     if(xhrObj.readyState==4 && 200 == xhrObj.status){
 5         eval(xhrObj.responseText);
 6     }
 7 };
 8 xhrObj.open('GET','A.js',true);
 9 xhrObj.send('');
10 function getXHRObject(){
11     var xhrObj=false;
12     try{
13         xhrObj=new XMLHttpRequest();
14     }catch(e){
15         var progid=['MSXML2.XMLHTTP.5.0','MSXML2.XMLHTTP.4.0','MSXML2.XMLHTTP.3.0',
16             'MSXML2.XMLHTTP','Microsoft.XMLHTTP'];
17             for(var i=0; i<progid.length; ++i){
18                 try{
19                     xhrObj=new ActiveXObject(progid[i]);
20                 }catch(e){
21                     continue;
22                 }
23                 break;
24             }
25     }finally{
26         return xhrObj;
27     }
28 }

 

二。XHR注入

该技术的原理是通过ajax技术获取脚本内容,并插入页面中作为行内脚本来执行的方式。该方式与上面的方式,因为都是通过ajax技术实现,因此都需要同域。

 1 var xhrObj=getXHRObject();
 2 xhrObj.onreadystatechange=function(){
 3     if(xhrObj.readyState==4){
 4         var scriptElem=document.createElement('script');
 5         codument.getElementsByTagName('head')[0].appendChild(scriptElem);
 6         scriptElem.text=xhrObj.responseText;
 7     }
 8 };
 9 xhrObj.open('GET','A.js',true);
10 xhrObj.send('');
11 function getXHRObject(){
12     var xhrObj=false;
13     try{
14         xhrObj=new XMLHttpRequest();
15     }catch(e){
16         var progid=['MSXML2.XMLHTTP.5.0','MSXML2.XMLHTTP.4.0','MSXML2.XMLHTTP.3.0',
17             'MSXML2.XMLHTTP','Microsoft.XMLHTTP'];
18             for(var i=0; i<progid.length; ++i){
19                 try{
20                     xhrObj=new ActiveXObject(progid[i]);
21                 }catch(e){
22                     continue;
23                 }
24                 break;
25             }
26     }finally{
27         return xhrObj;
28     }
29 }

三。script in iframe

该技术通过在iframe中加载一个html页面,并在该html页面中嵌入行内脚本来实现。该技术跟前面的XHR Eval技术一样需要对外部脚本进行重构,并且iframe本身消耗很高,并不是一个十分理想的技术。

<iframe src="A.html" width=0 height=0 frameborder=0 id=frame1></iframe>

四。script DOM element

该技术应该算是一种比较好的实践方式,它使用脚本动态的创建script DOM元素并设置其src属性,它不要求同域,也不会像上面几种方法那样需要对代码进行重构。

1 var scriptElem=document.createElement('script');
2 scriptElem.src='http:/anydomain.com/A.js';
3 document.getElementsByTagName('head')[0].appendChild(scriptElem);

五。script defer

defer属性是非常简单的防止脚本阻塞行为的方法,只需要在加载的脚本中添加一个属性即可:

<script defer src="A.js"></script>

但是这种方法只有IE和一些新浏览器支持它。

六。document.write script tag

该技术是使用document.write把HTML标签script写入到页面中,但是跟script defer一样,该技术只在IE中是并行加载脚本的。虽然它实现了并行加载脚本,但是在下载脚本的时候,浏览器仍然阻塞其他类型的资源。

document.write("<script type='text/javascript' src='A.js'></script>");

 

上面这些技术都能实现脚本的并行加载,但是每一种技术都有其缺陷,以至于我们不能紧靠其中一种方法就能够构建出我们所需要的功能。比如在脚本执行顺序上,script DOM element技术只在firefox和opera浏览器中能够确保执行顺序,这是它的一个缺陷。虽然script defer技术只在IE和一些新的浏览器中能够并行加载脚本,但是它对所有的浏览器都能够确保执行顺序,document.write script tag技术因为其只在部分浏览器中实现了并行下载,并且还会阻塞脚本之外的其他资源下载,因此不推荐使用该技术。在实际应用中我们需要根据具体情况综合来使用这些技术。