脚本加载技术
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技术因为其只在部分浏览器中实现了并行下载,并且还会阻塞脚本之外的其他资源下载,因此不推荐使用该技术。在实际应用中我们需要根据具体情况综合来使用这些技术。