码迷,mamicode.com
首页 > 其他好文 > 详细

脚本无阻塞加载

时间:2015-06-21 09:31:42      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:脚本无阻塞加载   web优化   动态脚本   




技术分享


                    (图片来源:http://www.cnblogs.com/sharpxiajun/p/4072396.html)
     
    这是清除浏览器缓存后,第一次访问百度首页的场景,在Firefox的瀑布图中可以看到:javascript文件下载完毕后,有一段时间没有请求处理。这段时间过后,请求才会接着执行,这段时间就是HTTP请求阻塞

    当浏览器遇到<script>标签时,浏览器会停止处理页面,先执行Javascript代码,然后再继续解析和渲染页面。在这个过程中,页面和用户的交互完全被阻塞了。通常表现为显示空白页面,用户无法浏览内容。

    现在的浏览器都支持并行下载文件,比如上图同时下载多个图片。而且,IE8 、FireFox3.5、Safari4和Chrome2都支持并行下载javascript文件,但是javascript文件的下载会阻塞其他资源的下载。尽管脚本的下载过程不会相互影响,但是页面仍然需要等待javascript的执行完毕才能继续。所以,新浏览器通过并行下载提高了性能,但是脚本阻塞问题仍然没有解决。

解决方法有:

(1)把<script>标签放到</body>闭合之前

  由于脚本会阻塞其他资源的下载,因此推荐把所有的<script>标签尽可能的放到<body>标签的底部。

(2)脚本合并,减少<script>标签的数量  

  每次遇到<script>标签,浏览器都要发一次HTTP请求。而HTTP请求耗时是web性能的最大的影响之一。

(3)动态脚本加载

       忙指示(忙指示现象有:浏览器选项卡的旋转圆圈,鼠标变成漏斗状,浏览器左下状态栏显示正在加载某某url)标记结束了,就表明页面的加载操作结束了,为了防止js脚本阻塞页面的加载。我们就要让那些不用于页面初始化展示的js代码的加载和执行在浏览器忙指示结束后触发。结束的标志就是onload事件触发,因此我们可以把那些有页面加载无关的js脚本放到onload事件里。


<span style="font-size:14px;">  var script=document.createElemetn("script");

  script.type="text/javascript";

  script.src="file.js";;

  document.getElementsByTagName("head").appendChild(script);</span>

使用动态脚本这种技术重点在于:文件的下载和执行过程不会阻塞页面其他进程。通常要把新创建的<script>标签添加到<head>标签里比添加到<body>标签里更保险。但是这种情况下,必须跟踪并确保脚本下载完成并准备就绪。
   标准浏览器:

  符合w3c标准的浏览器,script元素接收完成式,触发一个load事件。

var script =document.createElement("div");
script.type="text/javascript";

script.onload=function(){
  alert("ok");
};

script.src="file.js";

document.getElementsByTagName("head")[0].appendChild(script);




IE支持另外一种实现方式,触发readystatechange事件。<script>元素提供一个readyState属性,它的值在外链下载过程中不同阶段发生变化,属性有五个值:

  “uninitializd”   初始状态

   “loading”       开始下载
  
   “loaded”       下载完成

   “interactive”  数据下载完成但尚不可用

    “complete”  所有数据已准备就绪


最有用的的两个状态是:"loaded"和"complete"。

var script=document.createElement("script");

script.type="text/javascript";
//IE
script.onreadystatechange=function(){
   if(script.readyState=="loaded"||script.readyState="complete"){
   script.onreadystatechange=null;
   alert("ok");
 }
}

兼容标准及IE浏览器:

function loadScript(url ,callback){
    var script=document.createElement("script");
    script.src="text/javascript";
     
     if(script.readyState){//IE
         script.onreadyStateChange=function(){
         if(script.readyState=="loaded"||script.readyState=="complete"){
                    script.onreadystatechange=null;
  
                           callback();
                }
 
           };
    }else{//其他浏览器

     script.onload=function(){
        callback();
     };
  }
      script.src=url;
      document.getElementsByTagName("head")[0].appendChild(script);

 }
  
单个文件:

loadScript("file1.js",function(){

  alert("ok")
});

添加多个文件:
loadScript("file1.js",function(){
      loadScript("file2.js",function(){
         loadScript("file3.js",function(){
          alert("ok");
          });
      }); 
 });

添加多个文件会对管理带来困难,可以借助jquery的$.Deferred()和$.when()避免回调地狱。(http://blog.csdn.net/vuturn/article/details/45024767)

推荐的无阻塞模式

<script type="text/javascript" src="test.js"></script>

<script type="text/javascript">
loadScript("file.js",function(){
   alert("ok");
});
 
</script>


参考:(http://www.cnblogs.com/sharpxiajun/p/4072396.html
              《高性能JavaScript 》


脚本无阻塞加载

标签:脚本无阻塞加载   web优化   动态脚本   

原文地址:http://blog.csdn.net/vuturn/article/details/46574651

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!