代码改变世界

无阻塞脚本加载方案

2013-02-18 15:29  Justany_WhiteSnow  阅读(564)  评论(0编辑  收藏  举报

主要的无阻塞脚本加载方案有:

  • XHR Eval
  • XHR Injection
  • Script in Iframe
  • Script DOM Element
  • Script Defer
  • document.write Script Tag

关键问题就是怎么异步读取,以及怎么使脚本生效。

异步读取可利用XHR或者DOM元素进行,而使脚本生效则可通过Eval、动态创建script元素等方法完成。

 

XHR Eval

顾名思义,通过XHR读取脚本,通过Eval令脚本生效。

var xhrObj = new XMLHttpRequest();
xhrObj.onreadystatechange = function(){
    if(xhrObj.readyState == 4 && 200 == xhrObj.status){
        eval(xhrObj.responseText);
    }
};

xhrObj.open("GET", "A.js", true);
xhrObj.send("");

由于XMLHttpRequest本身不能跨域,所以该方法不能跨域。

 

XHR Injection

使用动态创建script元素,来写入脚本。

在某些情况下可能比上一种方法要快些。

var xhrObj = new XMLHttpRequest();
xhrObj.onreadystatechange = function(){
    if(xhrObj.readyState == 4){
        var scriptElem = document.createElement("script");
        document.getElementsByTagName("head")[0].appendChild(scriptElem);
        scriptElem.text = xhrObj.responseText;
    }
};
xhrObj.open("GET", "A.js", true);
xhrObj.send("");

由于是基于XMLHttpRequest读取的,所以依然不能跨域。 

 

Script in Iframe

由于Iframe是开销最高的DOM元素,这种方法还是尽量避免使用,而且这种方法也无法实现跨域。

 

Script DOM Element

可跨域方案,利用动态插入script元素来让脚本读取、生效。

var scriptElem = document.createElement("script");
scriptElem.src = "http://anydomain.com/A.js";
document.getElementByTagName("head")[0].appendChild(scriptElem);

 

Script Defer

原生方案。利用defer属性来防止脚本阻塞。

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

不过许多浏览器不支持该属性。

 

document.write Script Tag 

动态写脚本的另一种方案,不过只在IE中是并行下载的。

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