脚本无阻塞加载策略

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39956624/article/details/86411248

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

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

     解决办法有:

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

    由于脚本会阻塞其他资源的下载,因此推荐把所有的<script>标签尽可能的放到<body>标签的底部,以尽量减少对整个页面下载的影响。这是雅虎性能小组提出的优化JavaScript的首要规则:把脚本放在底部。

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

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

    3. 脚本延迟加载

    HTML 4为<script>标签定义了一个扩展属性:defer。defer 属性规定当页面已完成加载后,才会执行脚本。目前所有主流浏览器都支持defer。注意:defer 属性仅适用于外部脚本(只有在使用 src 属性时)。

    一个带有defer属性的<script>标签可以放置在文档的任何位置,它会在被解析时启动下载,直到DOM加载完成(在onload事件句柄被调用之前)。当一个defer的Javascript文件被下载时,它不会阻塞浏览器的其他处理过程,所以这些文件可以与其他资源一起并行下载。

扫描二维码关注公众号,回复: 5281129 查看本文章

   除了defer属性外,HTML 5 规范中引入了async属性,用于异步加载脚本。async与defer的相同点是采用并行下载,在下载过程中不会产生阻塞。区别在于执行时机,async是加载完成后自动执行,而defer需要等待页面完成后执行。这就会造成脚本的执行顺序和页面上脚本的排放顺序不一致,可能造成脚本依赖的问题(指async)

   4. 动态脚本加载

   DOM允许我们使用Javascript动态创建HTML的几乎所有文档内容,一个新的<script>元素可以非常容易的通过标准DOM创建:

  var script=document.createElemetn("script");
 
  script.type="text/javascript";
 
  script.src="file.js";;
 
  document.getElementsByTagName("head").appendChild(script);

    新的<script>元素加载file1.js源文件。此文件当元素添加到页面后立刻开始下载。此技术的重点在于:无论在何处启动下载,文件的下载和运行都不会阻塞其他页面处理过程。

    当文件使用动态脚本节点下载时,返回的代码通常立即执行(除了Firefox和Opera,它们将等待此前的所有动态脚本节点执行完毕)。

    大多数情况下,我们希望调用一个函数就可以实现Javascript文件的动态下载。下面的函数封装实现了标准实现和IE实现:

function loadScript(url, callback){  
    var script = document.createElement ("script") ;  
   script.type = "text/javascript";  
       
    if (script.readyState){ //IE  
       script.onreadystatechange = function(){  
         if (script.readyState == "loaded" || script.readyState == "complete"){  
           script.onreadystatechange = null;  
           callback();   
          }  
       };  
     }   
     else { //Others  
       script.onload = function(){ callback();  
     };   
   }  
   script.src = url;  
   document.getElementsByTagName("head")[0].appendChild(script);   
 }  
 
loadScript("file1.js", function(){  //调用  
    alert("File is loaded!");   
}); 

    如果需要加载多个js文件,一定要考虑清楚文件的加载顺序。你可以将下载操作串联起来以确保下载顺序:

loadScript("file1.js",function(){
      loadScript("file2.js",function(){
         loadScript("file3.js",function(){
          alert("ok");
          });
      }); 
 });

    此函数接受两个参数:Javascript文件的Url和一个当Javascript接收完成时触发的回调函数。属性检查用于决定监视哪种事件。最后一步src属性,并将javascript文件添加到head。

    动态脚本加载凭借它在跨浏览器兼容性和易用的优势,成为最通用的无阻塞加载解决方案。

猜你喜欢

转载自blog.csdn.net/qq_39956624/article/details/86411248