zoukankan      html  css  js  c++  java
  • 浏览器渲染阻塞与优化-详解推迟加载、异步加载。

    我认为一个前端工程师是否优秀,很大程度上取决于对前端性能上优化的功力。所以性能优化对前端真的很重要!!!
    本文介绍了什么是阻塞、为什么会阻塞?阻塞优化常用的5种方式以及他们的注意事项。
     
    浏览器渲染阻塞与优化
         什么是阻塞?在页面中我们通常会引用外部文件,而浏览器在解析HTML页面是从上到下依次解析、渲染,如果<head>中引用了一个a.js文件,而这个文件很大或者有问题,需要2秒加载,那么浏览器会停止渲染页面(此时是白屏显示,就是页面啥都没有),2秒后加载完成才会继续渲染,这个就是阻塞。
         为什么会阻塞?
              因为浏览器不知道a.js中执行了哪些脚本,会对页面造成什么影响,所以浏览器会等js文件下载并执行完成后才继续渲染,如果这个时间过长,会白屏。
              CSS文件也一样,因为CSS文件会对DOM的样式,布局,色彩,效果产生影响,所以浏览器会等CSS文件下载并执行完成后继续。
              为了页面的性能,要避免阻塞。
         
         阻塞优化-推迟加载、异步加载。
              推迟加载(延迟加载)
                   如果页面初始的渲染并不依赖于js或者CSS可以用推迟加载,就是最后在加载js和css,把引用外部文件的代码写在最后。比如一些按钮的点击事件,比如轮播图动画的脚本也可以放在最后。
          原理:因为浏览器默认是同步加载(这是为了避免重复触发“回流”和“重绘”),此时浏览器会从上到下逐条代码的加载、解析、渲染、执行。
    复制代码
     1 <html>
     2      <head>
     3     </head>
     4     <body>
     5         xxxxxxxxxxxxxxx
     6          <h1>推迟加载</h1>
     7          <script type="text/javascript" src="a.js"></script>
     8          <link href="a.css" rel="stylesheet" />
     9      </body>
    10 </html>
    复制代码
             defer延迟加载:
        在文档解析完成开始执行,并且在DOMContentLoaded事件之前执行完成,会按照他们在文档出现的顺序去下载解析。效果和把script放在文档最后</body>之前是一样的。
              注:defer最好用在引用外部文件中使用,用了defer不要使用document.write()方法;使用defer时最好不要请求样式信息,因为样式表可能尚未加载,浏览器会禁止该脚本等待样式表加载完成,相当于样式表阻塞脚本执行。
     
             异步加载(非阻塞加载)
              注:a.js文件中的代码如下,这样就会造成阻塞,因为如果我不点击确定,就无法继续渲染。
    1 alert("已暂停加载")
    2 alert("开始加载")
     
                1)async异步加载:就是告诉浏览器不必等到加载完外部文件,可以边渲染边下载,什么时候下载完成什么时候执行。用法就是“async“
    1  <script type="text/javascript" src="a.js" async></script>
                   注:实际测试中IE10+才支持,火狐,谷歌,Microsoft支持;用了async不要使用document.write()方法;使用async时最好不要请求样式信息,原因和defer一样。
          注2:async 在w3school中介绍是IE9就能支持,而IE9也是号称能支持,但是实际是不能完全支持的。
     
                2)script dom element法:这个方法是用js动态创建一个script元素添加在document中。
                       :支持全部浏览器(因为IE低版本IE10- 是单线程,所以要修改a.js才能显示正确的效果)
    1 setTimeout("alert('异步加载成功')",2000)     //测试IE时候a.js文件要修改
    复制代码
     1 <script type="text/javascript">
     2     (function() {
     3      var s = document.createElement('script');
     4      s.type = 'text/javascript';
     5      s.async = true;                                        //这句可以删除,但是效果不变。
     6      s.src = 'js/a.js';
     7      var x = document.getElementsByTagName('script')[0];
     8      x.parentNode.insertBefore(s, x);
     9  })();
    10 </script>
    复制代码
                        注意:这种方法会阻止onload事件,比如下面的代码,会等到a.js中的弹出框弹出后再执行。
    1 <script type="text/javascript">
    2     window.onload=function(){
    3         document.getElementById('div').innerHTML="onload完成"
    4     }
    5 </script>
    6 //写在html中
     
                 3)onload时异步加载:这个和script dom element法差不多但是他不是同时执行js和html,他是等html的文件,图片之类的、页面所有的资源全部加载完成后再下载执行js,这样的方法可以避免阻塞onload事件的触发。(兼容所有浏览器)
    复制代码
     1 (function() {
     2      function async_load(){
     3          var s = document.createElement('script');
     4          s.type = 'text/javascript';
     5          s.async = true;
     6          s.src = 'js/yibujiaz.js';
     7          var x = document.getElementsByTagName('script')[0];
     8          x.parentNode.insertBefore(s, x);
     9      }
    10      if (window.attachEvent)
    11          window.attachEvent('onload', async_load);
    12      else
    13          window.addEventListener('load', async_load, false);
    14  })();
    复制代码
              注:DOMContentLoaded与onload事件不同,DOMContentLoaded是页面解析完成,页面的dom元素可以使用,但是页面的图片、视频等资源可能还没加载完成
     
      我上面介绍的优化方式是常用的,除此之外还有其他的,比如异步加载还有AJAX异步加载,body onload异步加载等,这些用的比较少,有兴趣的工程师可以去查查相关资料。(如果你在博客园查基本上只要看一篇文章就好了,其他的基本上都说一样的,改都不会改;其实全网都差不多,都说互相转载复制的)。
     
     a.js全部代码
    1 // setTimeout("alert('异步加载成功')",2000)
    2 // alert("已暂停加载")
    3 // alert("开始加载")
     HTML全部代码
    复制代码
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>异步加载</title>
        <!-- <script type="text/javascript" src="js/yibujiaz.js" async></script> -->
    <script type="text/javascript">
        (function() {
         var s = document.createElement('script');
         s.type = 'text/javascript';
         s.src = 'js/yibujiaz.js';
         var x = document.getElementsByTagName('script')[0];
         x.parentNode.insertBefore(s, x);
     })();
    </script>
    <!-- <script type="text/javascript">
    (function() {
         function async_load(){
             var s = document.createElement('script');
             s.type = 'text/javascript';
             s.async = true;
             s.src = 'js/yibujiaz.js';
             var x = document.getElementsByTagName('script')[0];
             x.parentNode.insertBefore(s, x);
         }
         if (window.attachEvent)
             window.attachEvent('onload', async_load);
         else
             window.addEventListener('load', async_load, false);
     })();
    </script>
    <script type="text/javascript">
        window.onload=function(){
            document.getElementById('div').innerHTML="onload完成"
        }
    </script> -->
        <style type="text/css">
            div{
                200px;
                height:200px;
                background-color: blue;
                margin:0 auto;
            }
        </style>
    </head>
    <body>
        <div id="div">
        </div>
    </body>
    </html>
    复制代码
  • 相关阅读:
    MyBatis笔记:xml映射文件
    MyBatis笔记:xml配置文件
    JSP获取当前系统时间并显示
    使用<jsp:forward>和<jsp:param>
    JSP简单总结
    网页版学生管理系统简易版DOM
    当为servlet配置时出现servlet标签报错
    给js的事件驱动函数添加快捷键
    js的表格对象和DOM联合操作
    Centos7安装Greenplum5.3单机版教程
  • 原文地址:https://www.cnblogs.com/soundcode/p/5767812.html
Copyright © 2011-2022 走看看