由于浏览器是单线程的,因此脚本在载的时候会阻塞下载其它资源;虽然在现在浏览器已经有所改善,但仍然有待改进。
很显然,脚本必须按顺序执行,但没有必要按顺序下载,解决方法:
1。内嵌js
通常由于页面大小和缓存能带来更多好处,因此外部文件引入js更好一些;
在少数情况下,比如首页、少量js情况下尚可接受。
2。xhr eval
通过xmlhttprequest从服务器端获取脚本。
主要缺陷是,通过xhr获取的脚本必须部署在和主页面相同的域中。
复制代码 代码如下:
ajax.get(test.js, function (xhr) {
eval(xhr.responsetext);
});
3。xhr注入
使用xhr获取脚本并创建script标签。
同样,通过xhr获取的脚本必须部署在和主页面相同的域中。
复制代码 代码如下:
ajax.get('test.js', function (xhr) {
injectscript(xhr.responsetext);
});
function injectscript(scripttext) {
var s = document.createelement('script');
s.text = scripttext;
document.getelementsbytagname('head')[0].appendchild(s);
}
4。script in iframe
将需要的脚本放入到一个页面中,然后通过iframe来加载该页面。
缺点是iframe本身的开销比较大,另外浏览器安全机制不允许iframe中的js访问跨域的父页面,反之亦然。
5。script dom element
js动态创建script dom元素并设置其src属性。
复制代码 代码如下:
var scriptelem = document.createelement('script');
scriptelem.src = 'http://domain.com/test.js';
document.ge('head')[0].appendchild(scriptelem);
6。script defer
给script标签添加defer属性。
缺点是只有ie和一些新浏览器支持。
复制代码 代码如下:
7。document.write script tag
使用document.write把html标签script写入页面。
缺点是只有在ie中是并行加载脚本的。
复制代码 代码如下:
document.write(
有一个大家不曾广泛讨论的不同点是对于浏览器忙碌状态的影响,包括浏览器的状态栏、进度条、tab图标以及鼠标。
当你加载多个彼此间有依赖关系的脚本时,还需要一种能够保证执行顺序的技术。
技术
并行下载
可以跨域
存在script标签
忙碌指示
顺序保证
大小 (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
在大多数情况下,script dom element是一个好的选择。这种方式适用于所有的浏览器,而且没有跨域的限制,实现起来也非常的简单和易于理解。唯一的缺点是不能保证各个脚本的执行顺序。如果需要加载多个有依赖关系的脚本,应该将这些脚本拼成一个来保证其按需要的顺序执行,或者使用别的技术。
目前异步加载时保持执行顺序的方法有下面几种,由于篇幅原因,暂不详细描述。
单个脚本
1、hardcoded callback
2、window onload
3、timer
4、script onload
5、degrading script tags
多个脚本
1、managed xhr
2、dom element and doc write
本文参考《高性能网站建设进阶指南》