主要的无阻塞脚本加载方案有:
- 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>");