相信各位都知道所有浏览器在下载JS的时候,会阻止一切其他活动,比如其他资源的下载,内容的呈现等等。至到JS下载、解析、执行完毕后才开始继续并行下载其他资源并呈现内容。
首先我来解释一下原因
先说说浏览器构造页面的原理
当浏览器从服务器接收到了HTML文档,并把HTML在内存中转换成DOM树,在转换的过程中如果发现某个节点(node)上引用了CSS或者 IMAGE,就会再发1个request去请求CSS或image,然后继续执行下面的转换,而不需要等待request的返回,当request返回 后,只需要把返回的内容放入到DOM树中对应的位置就OK。但当引用了JS的时候,浏览器发送1个js request就会一直等待该request的返回。
那这个构造原理和JS的加载有什么相关的呢?
因为浏览器需要1个稳 定的DOM树结构,而JS中很有可能有代码直接改变了DOM树结构,比如使用document.write 或 appendChild,甚至是直接使用的location.href进行跳转,浏览器为了防止出现JS修改DOM树,需要重新构建DOM树的情况,所以 就会阻塞其他的下载和呈现。
下图是访问blogjava首页的时间瀑布图,可以看出来开始的2个image都是并行下载的,而后面的2个JS都是阻塞下载的(1个1个下载)。
回归正题,通常一些大流量的网站都会在页面中嵌入广告JS,通过这些JS来进行网赚
但是很多时候这些JS反而成为妨碍网站加载的阻碍
这时候就要用到异步加载了
主要的步骤:
- 创建一个script的DOM节点;
- 对其的type属性赋值为text/javascript;
- 再指定它的src属性为要加载的js文件URL;
- 把这个DOM节点加入到页面中。
方法1:
这个方法有BUG,就是当加载的js文件含有document.write语句的时候,IE会无法正常加载,而FF则会显示空白的网页,所以说这个方法只是拿出来给大家看看,不建议使用
function include_js(path,reload)
{
var scripts = document.getElementsByTagName(“script”);
if (!reload)
for (var i=0;i<scripts.length;i++)
if (scripts[i].src && scripts[i].src.toLowerCase() == path.toLowerCase() ) return;
var sobj = document.createElement(‘script’);
sobj.type = “text/javascript”;
sobj.src = path;
var headobj = document.getElementsByTagName(‘head’)[0];
headobj.appendChild(sobj);
}
{
var scripts = document.getElementsByTagName(“script”);
if (!reload)
for (var i=0;i<scripts.length;i++)
if (scripts[i].src && scripts[i].src.toLowerCase() == path.toLowerCase() ) return;
var sobj = document.createElement(‘script’);
sobj.type = “text/javascript”;
sobj.src = path;
var headobj = document.getElementsByTagName(‘head’)[0];
headobj.appendChild(sobj);
}
这种BUG当然会有解决的办法,就是重写document.write
首先是在需要write的区域加上
之后在上面的代码中的include_js之前加上一句
document.write = function (s)
{
document.getElementById(‘jsdiv’).innerHTML+=s;
return false;
}
{
document.getElementById(‘jsdiv’).innerHTML+=s;
return false;
}
这样JS就能正常的异步加载了