zoukankan      html  css  js  c++  java
  • js、css的阻塞问题

    js、css的阻塞问题

      这篇文章主要是探索js、css的加载顺序及其影响问题。

      下面的代码可以让浏览器阻塞:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>阻塞代码</title>
    </head>
    <body>
      <script>
        // 阻塞代码,参数单位s
        function blocking(blockingTime) {
          function getTime() {
            return new Date().getTime();
          }
          var startTime = getTime();
          // getTime()得到的时间单位是ms,所以乘1000
          while (getTime() < startTime + blockingTime*1000);
        }
        blocking(5);
      </script>
      <h3>hello</h3>
    </body>
    </html>

    测试一:

    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="utf-8">
      <title>JS/css</title>
      <script>var start = +new Date;</script>
      <script>
        var end = +new Date;
        console.log(end-start);
      </script>
      <link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet">
    </head>  
    
    <body>
    </body>
    
    </html>

    注:其中的+为单目运算符,可以将对象转化为数字。

    显然,在控制台输出的结果为0。因为上面的js语句刚刚执行完,就执行下面的语句,所以时间间隔几乎为0。

    测试二:

    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="utf-8">
      <title>JS/css</title>
      <script>var start = +new Date;</script>
      <link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet">
      <script>
        var end = +new Date;
        console.log(end-start);
      </script>
    </head>  
    
    <body>
    </body>
    
    </html>

    这个测试中,我将css置于两个script之间,最后的输出结果为2870, 当然这个值是个随机数,一定是远远大于0的。

    然后我们在打开开发者工具的Network的情况下点击刷新,这时再看console控制台打印出的值为2967, 然后我们观察加载css所需的时间:

    2.97s,也就是2967ms。

    结论: 外部样式的加载会阻塞在它之后的<script>语句的加载,并且<script>是在<link>完全加载结束之后执行的。

      

     

     

    测试3:

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>JS/CSS</title>
    
      <script>var start = +new Date;</script>
      <link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet">
      <script>
        var endAfterCss = +new Date;
        console.log("css", (endAfterCss - start));
      </script>
    
    </head>
    <body>
      
      <script src="http://udacity-crp.herokuapp.com/time.js?rtt=1&a"></script>
    
      <div id="result"></div>
      
      <script>
        var endAfterScript = +new Date;
        console.log("js",(endAfterScript - start));
      </script>
      
    </body>
    </html>

    在console控制台的输出如下:

    我们可以看到在两者之间还有一个外部的script标签,为什么两者的执行却是几乎同时发生的呢?

      我们同样在network中刷新,然后得到的console控制台信息如下:

        然后查看network,并查看外部css的详情, 如下所示:

     可以看出,css的加载时间就是3.12s,然后它的加载阻塞了下面的script的执行,css一旦加载完毕,下面的script立即执行,所以得到了3118这个值。这个很容易理解。

     注意观察上图,可以发现外部css和外部js的加载时间几乎是同时的,也就是说外部css的加载不会影响到下面的js的加载。

    但是为什么在外部js文件下面的js却是3130呢? 外部的script的加载不是也需要一定的时间吗?我们看看js的加载时间。

     我们可以看到,外部js的加载时间仅为1.38s,也就是说在外部css还没有加载完的时候js就加载结束了,但是它并没有执行,而是等到css加载完了之后才执行的。所以才会得到3130这个数值。其中的差值就是js执行的时间。

    结论: 在css加载的过程中,下面的外部js同时也会加载,只是下面的外部js必须等到上面的css加载完成之后才能执行。 并且js会阻断下面的js的执行,因为js的执行是单线程的,所以在外部css执行结束之后,下面的内联css才会继续执行。

     

    测试4:

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>JS/CSS</title>
    
      <script>var start = +new Date;</script>
      <link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet">
      <link rel="stylesheet" href="https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/mancard/css/card_min_dee38e45.css">
      <script>
        var endAfterCss = +new Date;
        console.log("css", (endAfterCss - start));
      </script>
    
    </head>
    <body>
      
      <script src="http://udacity-crp.herokuapp.com/time.js?rtt=1&a"></script>
    
      <div id="result"></div>
      
      <script>
        var endAfterScript = +new Date;
        console.log("js",(endAfterScript - start));
      </script>
      
    </body>
    </html>

    network如下:

    即页面中的两个css是同时加载的,并且js也是,即两个css和js都是同时加载的,我的第二个css在html中是在js上面的,但是这里显示js却是先加载的,也就是说第一个css加载的时候,后面的js和css是同时加载的,至于谁最先加载,就不好说了,看下图,在代码没有改变的情况下,js是最后加载的。

    说明:黄色部分为 Initial Connection ,即初始链接网络所消耗的时间,这种情况的发生往往是因为多个请求导致的

    如果我将耗时较长的css删除,那么我们得到的瀑布流如下所示:

    可以看到这里确是js先加载的!

    console控制台输出的结果是:

    所以说link的加载不会影响js的加载是完全正确的。

    结论:  如果同时具有两个link,一个外部的css,那么此三者是同时加载的,只是无法确定后面两者的先后关系。同样的,必须要在css加载结束之后js才能执行。

        如果只有一个css、一个js,那么两者的加载顺序是不确定的。

    测试5:

      异步加载js

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>JS Bin</title>
      <script>var start = +new Date;</script>
      <link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet">
      
    </head>
      
    <body>
      test
      <script src="http://udacity-crp.herokuapp.com/time.js?rtt=1&a" async></script>
      <div id="result"></div>
      <script>
        var end = +new Date;
        console.log(end - start);
      </script>
      
    </body>
    </html>

      表现如下:

      可以看出,css的加载时间为2.37s, 在控制台的输出时间为2368ms,也就是说在css执行完成之后,外部js并没有阻碍下面的内联js的执行,而在页面中我们可以看到2094.6450000,这是指外联js执行的时间,我们在console控制台中可以看到外联js的执行时间为2.07s,也就是说在外联js加载完成之后就立即执行了,而没有等待外联css加载完毕再执行。

      说明:再外联js的代码中我们使用了window.performance.now()方法,这个方法返回的是页面开启后的时间,且其单位为ms, 小数点之后保留了13位,这样的好处是较之于Data.now()更有利于我们检测性能。

      更多关于window.performance.now()的内容可以参照这篇文章:http://www.cnblogs.com/xiaohuochai/archive/2017/03/09/6523397.html

    结论: 使用了async属性之后,就可以实现js的异步加载,即该文件的执行不必等待外联css文件加载完成就可以执行,并且也不会阻塞后面的js的加载。

    测试6:

      创建<script>元素实现加载外部js

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>JS Bin</title>
      <script>var start = +new Date;</script>
      <link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet">
      
    </head>
      
    <body>
      test
      <script> 
        var script = document.createElement('script');
        script.src = "http://udacity-crp.herokuapp.com/time.js?rtt=1&a";
        document.getElementsByTagName('head')[0].appendChild(script);
      </script>
      <div id="result"></div>
      <script>var end = +new Date;document.getElementById("result").innerHTML = end-start;</script>
      
    </body>
    </html>

       我们可以看到瀑布流如下所示:

      也就是说,在这种情况下,只有css完全加载完成之后,js才会加载。

    结论:  在script标签是动态创建的情况下,其加载的优先级较低,会在css完全加载之后再加载。 注意观察: js的优先级为Low,所以会在css完全加载结束之后加载。

    因为动态创建标签也是js语句,之前降到了语句的执行会被css阻塞。

    测试7:

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>JS Bin</title>
      <script>var start = +new Date;</script>
      <link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet">
      <script>
      var end0 = +new Date;
      console.log(end0 - start);
      </script>
      
    </head>
      
    <body>
       <script src="http://udacity-crp.herokuapp.com/time.js?rtt=1&a"></script>
      <div id="result"></div>
      <script>
      var end1 = +new Date;
      console.log(end1 - start);
      </script>
    
      <script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script>
      <script>
      var end2 = +new Date;
      console.log(end2 - start);
      </script>
      
    </body>
    </html>

    输出如下所示:

    瀑布流如下所示:

    可以看出css加载的过程中,后面的两个js同时加载,且加载的速度比css要快,这时css阻塞着后面的加载,一旦css加载完毕,已经加载好的js立即执行。

    参考文章:http://www.cnblogs.com/shinnyChen/p/3762704.html

  • 相关阅读:
    如何挑选适合的前端框架
    为什么做java的web开发我们会使用struts2,springMVC和spring这样的框架?
    Spring框架文档与API(4.3.6版本)
    Spring Framework Ecosystem – Introduction to Spring Projects
    What is the difference between J2EE and Spring
    WPS添加页码不是从首页开始
    C语言文件方式输入与输出(最简洁方便实用的一种方式)
    hibernate---注解--CascadeType属性
    hibernate------java-delete-insert-update
    hibernate---注释 ----(购物:人顾客售货员boss)
  • 原文地址:https://www.cnblogs.com/zhuzhenwei918/p/6546083.html
Copyright © 2011-2022 走看看