精华内容
下载资源
问答
  • 这几天因项目需求,要实现一系列的js文件加载的问题,于是,就按照常规思路写了一通,悲催的是... 常规理解就是浏览器在加载js时候会阻塞浏览器的渲染操作,但页面性能决定不希望我们在加载js的时候影响页面的渲染,

     这几天因项目需求,要实现一系列的js文件加载的问题,于是,就按照常规思路写了一通,悲催的是测试后发现问题重重;

    为什么会有这么多问题,仔细想来还是对浏览器加载js的原理理解不透,于是我翻阅了大量的资料和自己的一些实践,总结出来以下的内容;

    1、js在浏览器中的阻塞

      常规理解就是浏览器在加载js时候会阻塞浏览器的渲染操作,但页面性能决定不希望我们在加载js的时候影响页面的渲染,所以我们经常会把js文件放到body之前去加载。而不会把它放在head里去阻塞页面的渲染。那么问题来了,如果我们把js放在head里,浏览器是怎么去执行它的呢,是按顺序加载还是并行加载呢?

    其实在旧的浏览器下,都是按照先后顺序来加载的,这就保证了加载的js依赖不会发生问题。但是新的浏览器已经开始允许并行加载js了,也就是说我可以同时下载js文件,但是还是先后顺序执行文件的。

    2、document.write 使用

    我们一般会用document.write来生成一段广告,经常这样操作:document.write('<script id="posAD" type="text/JavaScript" src="http://192.168.3.107:888/control.js?platformcode=tcy&postioncode=A1&filecode=10030"><\/script>');

    这样操作也是阻塞的;有同学就问了,你这是外联js,那么内链的呢,我也做过测试,一样的,同样会阻塞。

    这样使用的时候一定要记住,要确保他是在dom ready之前去执行,否则它将会重新渲染整个页面。

    3、那么如何实现非阻塞呢,那么就需要动态加载js了,通过appendChild(script)这种方式去异步加载js了,其实还可以用xhr对象来处理,但是这样只能解决非跨域问题,跨域xhr就无能为力了。还有一种办法就是新浏览器的defer 和 async 属性了,这样你把它写到head里也不会阻塞浏览器的渲染了。

     

    于是在我明白上述的这样东东之后,我简单的实现一个动态加载js模块:

        //loadJS模块
        (function () {
    
          var loadJS = function (deps, callback) {
            if(typeof deps == 'string') {
              deps = [deps];
            }
    
            var len = deps.length;
            var   j = 0 ;
            var  fn = function (){
                  j++;
                  if(j == len) {
                    callback.apply(window);
                  }
            };
    
            for(var i = 0 ; i < deps.length ; i++) {
                   _loadMod(deps[i],fn);       
            };
          };
    
          var _loadMod = function(url,fn) {
            var    head = document.head || document.getElementsByTagName('head')[0] || document.documentElement;
            var  script = document.createElement('script');
                 script.type = 'text/javascript';
                 script.charset = 'utf-8';
                 script.async = true;
                 script.src = url;
                 script.onload = script.onreadystatechange = function() {
                 if (!script.readyState || script.readyState in {'loaded': 1, 'complete': 1}) {
                        script.onload = script.onreadystatechange = null;
                        fn();
                        head.removeChild(script);
                        script = null;
                    }
                 }
                 head.insertBefore(script, head.firstChild);
           } 
    
           window.loadJS = loadJS;
    
        })();

    以上内容也是我这两天初步终结出来的,有不对的地方还希望各位童鞋指正。

    有兴趣的还可以参考这两篇博客:http://www.w3cfuns.com/blog-5443287-5401014.html 或则 http://www.cnblogs.com/hongcaomao/archive/2012/03/27/javascript_loadad.html

    展开全文
  • 可能大家都知道,js执行会阻塞DOM树的解析和渲染,那么css加载会阻塞DOM树的解析和渲染吗?接下来,我们就一起来分析一下。 原理解析 那么为什么会出现上面的现象呢?我们从浏览器的渲染过程来解析下。 不同的浏览器...
  • 外部JS阻塞下载

    2019-10-08 22:41:41
    所有浏览器在下载JS的时候,阻止一切其他活动,比如其他资源的下载,内容的呈现等等。至到JS下载、解析、执行完毕后... 有人问:为什么JS不能像CSS、image一样并行下载了?这里需要简单介绍一下浏览器构造页面...

    转载于:http://www.cnblogs.com/mofish/archive/2011/09/29/2195256.html

    所有浏览器在下载JS的时候,会阻止一切其他活动,比如其他资源的下载,内容的呈现等等。至到JS下载、解析、执行完毕后才开始继续并行下载其他资源并呈现内容。

        有人会问:为什么JS不能像CSS、image一样并行下载了?这里需要简单介绍一下浏览器构造页面的原理,
    当浏览器从服务器接收到了HTML文档,并把HTML在内存中转换成DOM树,在转换的过程中如果发现某个节点(node)上引用了CSS或者 IMAGE,就会再发1个request去请求CSS或image,然后继续执行下面的转换,而不需要等待request的返回,当request返回 后,只需要把返回的内容放入到DOM树中对应的位置就OK。但当引用了JS的时候,浏览器发送1个js request就会一直等待该request的返回。因为浏览器需要1个稳定的DOM树结构,而JS中很有可能有代码直接改变了DOM树结构,比如使用 document.write 或 appendChild,甚至是直接使用的location.href进行跳转,浏览器为了防止出现JS修改DOM树,需要重新构建DOM树的情况,所以 就会阻塞其他的下载和呈现.

        阻塞下载图:下图是访问blogjava首页的时间瀑布图,可以看出来开始的2个image都是并行下载的,而后面的2个JS都是阻塞下载的(1个1个下载)。

    嵌入JS的阻塞下载

    嵌入JS是指直接写在HTML文档中的JS代码。上面说了引用外部的JS会阻塞其后的资源下载和其后的内容呈现,哪嵌入的JS又会是怎样阻塞的了,看下面的列2个代码:
        代码1: 

      < div >
          < ul >
              < li > blogjava </ li >
              < li > CSDN </ li >
              < li > 博客园 </ li >
              < li > ABC </ li >
              < li > AAA </ li >
          < ul >    
      </ div >
      < script  type ="text/javascript" >
         // 循环5秒钟
          var  n  =  Number( new  Date());
      var  n2  =  Number( new  Date());
     while ((n2  -  n)  <  ( 6 * 1000 )){
        n2  =  Number( new  Date());
      }
      </ script >
    < div >
          < ul >
              < li > MSN </ li >
              < li > GOOGLE </ li >
              < li > YAHOO </ li >
          < ul >    
      </ div >

    运行后,会发现代码1中,在前5秒中页面上是一篇空白,5秒中后页面全部显示。 代码2中,前5秒中blogjava,csdn等先显示出来,5秒后MSN才显示出来。
    可以看出嵌入JS会阻塞所有内容的呈现,而外部JS只会阻塞其后内容的显示,2种方式都会阻塞其后资源的下载。

    嵌入JS导致CSS阻塞加载的问题

    CSS怎么会阻塞加载了?CSS本来是可以并行下载的,在什么情况下会出现阻塞加载了(在测试观察中,IE6下CSS都是阻塞加载,下面的测试在非IE6下进行):
       代码1(为了效果,这里选择了1个国外服务器的CSS):

    < html  xmlns ="http://www.w3.org/1999/xhtml" >
         < head >
           < title > js test </ title >
           < meta  http-equiv ="Content-Type"  content ="text/html; charset=UTF-8"   /> 
           < link  type ="text/css"  rel ="stylesheet"  href ="http://69.64.92.205/Css/Home3.css"   />
         </ head >
         < body >
             < img  src ="http://www.blogjava.net/images/logo.gif"   />< br  />
              < img  src ="http://csdnimg.cn/www/images/csdnindex_piclogo.gif"   />
         </ body >
    </ html >

    时间瀑布图:

    代码2(只加了1个空的嵌入JS):

    < head >
         < title > js test </ title >
         < meta  http-equiv ="Content-Type"  content ="text/html; charset=UTF-8"   /> 
       < link  type ="text/css"  rel ="stylesheet"  href ="http://69.64.92.205/Css/Home3.css"   />
       < script  type ="text/javascript" >
             function  a(){}
       </ script >
    </ head >
    < body >
             < img  src ="http://www.blogjava.net/images/logo.gif"   />< br  />
             < img  src ="http://csdnimg.cn/www/images/csdnindex_piclogo.gif"   />
    </ body >

      时间瀑布图:

           从时间瀑布图中可以看出,代码2中,CSS和图片并没有并行下载,而是等待CSS下载完毕后才去并行下载后面的2个图片,当CSS后面跟着嵌入的JS的时候,该CSS就会出现阻塞后面资源下载的情况。
        有人可能会问,这里为什么不说说嵌入的JS阻塞了后面的资源,而是说CSS阻塞了? 想想我们现在用的是1个空函数,解析这个空函数1ms就够,而后面2个图片是等CSS下载完1.3s后才开始下载。大家还可以试试把嵌入JS放到CSS前 面,就不会出现阻塞的情况了。
      
        根本原因:因为浏览器会维持html中css和js的顺序,样式表必须在嵌入的JS执行前先加载、解析完。而嵌入的JS会阻塞后面的资源加载,所以就会出现上面CSS阻塞下载的情况。

    嵌入JS应该放在什么位置

       1、放在底部,虽然放在底部照样会阻塞所有呈现,但不会阻塞资源下载。
       
       2、如果嵌入JS放在head中,请把嵌入JS放在CSS前面。
       
       3、使用defer
       
       4、不要在嵌入的JS中调用运行时间较长的函数,如果一定要用,可以用setTimeout来调用

    PS:很多网站喜欢在head中嵌入JS,并且习惯放在CSS后面,比如看到的www.qq.com,当然也有很多网站是把JS放到CSS前面的,比如yahoo,google

    转载于:https://www.cnblogs.com/M-D-Luffy/p/4373947.html

    展开全文
  • 一直以为如果js写在head里就需要用window.onload=function(){},如果写在body结尾前面,则不用写,但是为什么下面的代码不写的话,最开始载入页面img的高度全部为0?(就是看不见图)执行js需要等img加载好吗,这...
  • 可能大家都知道,js执行会阻塞DOM树的解析和渲染,那么css加载会阻塞DOM树的解析和渲染吗?接下来,我们就一起来分析一下。原理解析那么为什么会出现上面的现象呢?我们从浏览器的渲染过程来解析下。不同的浏览器...

    可能大家都知道,js执行会阻塞DOM树的解析和渲染,那么css加载会阻塞DOM树的解析和渲染吗?接下来,我们就一起来分析一下。

    原理解析

    那么为什么会出现上面的现象呢?我们从浏览器的渲染过程来解析下。

    不同的浏览器使用的内核不同,所以他们的渲染过程也是不一样的。目前主要有两个:

    webkit渲染过程

    85073ea74212c5bc23eb15fd2269cdf5.png

    Gecko渲染过程

    7c7a7329917e3584fa2e3310ba8efab2.png

    从上面两个流程图我们可以看出来,浏览器渲染的流程如下:

    1. HTML解析文件,生成DOM Tree,解析CSS文件生成CSSOM Tree
    2. 将Dom Tree和CSSOM Tree结合,生成Render Tree(渲染树)
    3. 根据Render Tree渲染绘制,将像素渲染到屏幕上。

    从流程我们可以看出来

    1. DOM解析和CSS解析是两个并行的进程,所以这也解释了为什么CSS加载不会阻塞DOM的解析。
    2. 然而,由于Render Tree是依赖于DOM Tree和CSSOM Tree的,所以他必须等待到CSSOM Tree构建完成,也就是CSS资源加载完成(或者CSS资源加载失败)后,才能开始渲染。因此,CSS加载是会阻塞Dom的渲染的。
    3. 由于js可能会操作之前的Dom节点和css样式,因此浏览器会维持html中css和js的顺序。因此,样式表会在后面的js执行前先加载执行完毕。所以css会阻塞后面js的执行。

    DOMContentLoaded

    对于浏览器来说,页面加载主要有两个事件,一个是DOMContentLoaded,另一个是onLoad。而onLoad没什么好说的,就是等待页面的所有资源都加载完成才会触发,这些资源包括css、js、图片视频等。

    而DOMContentLoaded,顾名思义,就是当页面的内容解析完成后,则触发该事件。那么,正如我们上面讨论过的,css会阻塞Dom渲染和js执行,而js会阻塞Dom解析。那么我们可以做出这样的假设

    1. 当页面只存在css,或者js都在css前面,那么DomContentLoaded不需要等到css加载完毕。
    2. 当页面里同时存在css和js,并且js在css后面的时候,DomContentLoaded必须等到css和js都加载完毕才触发。

    我们先对第一种情况做测试:

      css阻塞

    实验结果如下图:

    276ddd4f44b48a57ba7fd7c7662c2713.gif

    从动图我们可以看出来,css还未加载完,就已经触发了DOMContentLoaded事件了。因为css后面没有任何js代码。

    接下来我们对第二种情况做测试,很简单,就在css后面加一行代码就行了

      css阻塞

    实验结果如下图:

    1591aad7e501c9f0f3dcac157224e143.gif

    我们可以看到,只有在css加载完成后,才会触发DOMContentLoaded事件。因此,我们可以得出结论:

    1. 如果页面中同时存在css和js,并且存在js在css后面,则DOMContentLoaded事件会在css加载完后才执行。
    2. 其他情况下,DOMContentLoaded都不会等待css加载,并且DOMContentLoaded事件也不会等待图片、视频等其他资源加载。

    总结

    由上所述,我们可以得出以下结论:

    1. css加载不会阻塞DOM树的解析
    2. css加载会阻塞DOM树的渲染
    3. css加载会阻塞后面js语句的执行、

    因此,为了避免让用户看到长时间的白屏时间,我们应该尽可能的提高css加载速度,比如可以使用以下几种方法:

    1. 使用CDN(因为CDN会根据你的网络状况,替你挑选最近的一个具有缓存内容的节点为你提供资源,因此可以减少加载时间)
    2. 对css进行压缩(可以用很多打包工具,比如webpack,gulp等,也可以通过开启gzip压缩)
    3. 合理的使用缓存(设置cache-control,expires,以及E-tag都是不错的,不过要注意一个问题,就是文件更新后,你要避免缓存而带来的影响。其中一个解决防范是在文件名字后面加一个版本号)
    4. 减少http请求数,将多个css文件合并,或者是干脆直接写成内联样式(内联样式的一个缺点就是不能缓存)
    展开全文
  • 可能大家都知道,js执行会阻塞DOM树的解析和渲染,那么css加载会阻塞DOM树的解析和渲染吗?接下来,我们就一起来分析一下。原理解析那么为什么会出现上面的现象呢?我们从浏览器的渲染过程来解析下。不同的浏览器...

    可能大家都知道,js执行会阻塞DOM树的解析和渲染,那么css加载会阻塞DOM树的解析和渲染吗?接下来,我们就一起来分析一下。

    原理解析

    那么为什么会出现上面的现象呢?我们从浏览器的渲染过程来解析下。

    不同的浏览器使用的内核不同,所以他们的渲染过程也是不一样的。目前主要有两个:

    webkit渲染过程

    e146ec879cacc02ab6e9b557d0067c49.png

    Gecko渲染过程

    f0c6ae59f7142c3c142914bc2a427b95.png

    从上面两个流程图我们可以看出来,浏览器渲染的流程如下:

    1. HTML解析文件,生成DOM Tree,解析CSS文件生成CSSOM Tree
    2. 将Dom Tree和CSSOM Tree结合,生成Render Tree(渲染树)
    3. 根据Render Tree渲染绘制,将像素渲染到屏幕上。

    从流程我们可以看出来

    1. DOM解析和CSS解析是两个并行的进程,所以这也解释了为什么CSS加载不会阻塞DOM的解析。
    2. 然而,由于Render Tree是依赖于DOM Tree和CSSOM Tree的,所以他必须等待到CSSOM Tree构建完成,也就是CSS资源加载完成(或者CSS资源加载失败)后,才能开始渲染。因此,CSS加载是会阻塞Dom的渲染的。
    3. 由于js可能会操作之前的Dom节点和css样式,因此浏览器会维持html中css和js的顺序。因此,样式表会在后面的js执行前先加载执行完毕。所以css会阻塞后面js的执行。

    DOMContentLoaded

    对于浏览器来说,页面加载主要有两个事件,一个是DOMContentLoaded,另一个是onLoad。而onLoad没什么好说的,就是等待页面的所有资源都加载完成才会触发,这些资源包括css、js、图片视频等。

    而DOMContentLoaded,顾名思义,就是当页面的内容解析完成后,则触发该事件。那么,正如我们上面讨论过的,css会阻塞Dom渲染和js执行,而js会阻塞Dom解析。那么我们可以做出这样的假设

    1. 当页面只存在css,或者js都在css前面,那么DomContentLoaded不需要等到css加载完毕。
    2. 当页面里同时存在css和js,并且js在css后面的时候,DomContentLoaded必须等到css和js都加载完毕才触发。

    我们先对第一种情况做测试:

      css阻塞

    实验结果如下图:

    8f3ae52d859956268e32aeebb441eff8.gif

    从动图我们可以看出来,css还未加载完,就已经触发了DOMContentLoaded事件了。因为css后面没有任何js代码。

    接下来我们对第二种情况做测试,很简单,就在css后面加一行代码就行了

      css阻塞

    实验结果如下图:

    f9e644ceb422135d70247ba39c08475b.gif

    我们可以看到,只有在css加载完成后,才会触发DOMContentLoaded事件。因此,我们可以得出结论:

    1. 如果页面中同时存在css和js,并且存在js在css后面,则DOMContentLoaded事件会在css加载完后才执行。
    2. 其他情况下,DOMContentLoaded都不会等待css加载,并且DOMContentLoaded事件也不会等待图片、视频等其他资源加载。

    总结

    由上所述,我们可以得出以下结论:

    1. css加载不会阻塞DOM树的解析
    2. css加载会阻塞DOM树的渲染
    3. css加载会阻塞后面js语句的执行、

    因此,为了避免让用户看到长时间的白屏时间,我们应该尽可能的提高css加载速度,比如可以使用以下几种方法:

    1. 使用CDN(因为CDN会根据你的网络状况,替你挑选最近的一个具有缓存内容的节点为你提供资源,因此可以减少加载时间)
    2. 对css进行压缩(可以用很多打包工具,比如webpack,gulp等,也可以通过开启gzip压缩)
    3. 合理的使用缓存(设置cache-control,expires,以及E-tag都是不错的,不过要注意一个问题,就是文件更新后,你要避免缓存而带来的影响。其中一个解决防范是在文件名字后面加一个版本号)
    4. 减少http请求数,将多个css文件合并,或者是干脆直接写成内联样式(内联样式的一个缺点就是不能缓存)
    展开全文
  • js具有阻塞特性,当浏览器在执行js代码时,不能同时做其它事情,即每次出现都会让页面等待脚本的解析和执行(不论JS是内嵌的还是外链的),JS代码执行完成后,才...有人问:为什么JS不能像CSS、image一样并行下载了?
  • 首先说结论:不论是内联还是外链js都会阻塞后续dom的解析和渲染如果把JavaScript放在页面顶部,下载和解析JavaScript的时间里面,dom迟迟得不到解析和渲染,浏览器一直处于白屏,所以把JavaScript文件放在页面底部更...
  • 有人问:为什么JS不能像CSS、image一样并行下载了?这里需要简单介绍一下浏览器构造页面的原理, 当浏览器从服务器接收到了HTML文档,并把HTML在内存中转换成DOM树,在转换的过程中如果发现某个节点(nod...
  • 高并发外部JS阻塞下载

    千次阅读 2015-06-17 18:02:51
     有人问:为什么JS不能像CSS、image一样并行下载了?这里需要简单介绍一下浏览器构造页面的原理, 当浏览器从服务器接收到了HTML文档,并把HTML在内存中转换成DOM树,在转换的过程中如果发现某个节点(node)上...
  • 加载 JS 并执行的时候,会阻塞其他资源的加载。这是因为 JS 可能会有 DOM 、样式等等操作,所以浏览器要先加载这段 JS 并执行,再加载放在它后面的 HTML、CSS。因此,加入一段巨大的 JS 放在最上面,浏览器首先要...
  • 为什么CSS放头部,JS放底部

    千次阅读 2018-12-25 09:03:21
    然而,为什么呢?原因如下: CSS 不会阻塞 DOM 的解析,但会阻塞 DOM 渲染。 JS 阻塞 DOM 解析,但浏览器会"偷看"DOM,预先下载相关资源。 浏览器遇到 &lt;script&gt;且没有defer或async属性的...
  • javascript为什么是单线程的,这么做有什么好处? 因为历史原因,js的出现主要是为了解决页面的交互和操作DOM,如果是多线程的,就带来比较复杂的同步问题。 比如两个线程同时操作一个DOM,那最终页面显示上...
  • javascript为什么是单线程的,这么做有什么好处? 因为历史原因,js的出现主要是为了解决页面的交互和操作DOM,如果是多线程的,就带来比较复杂的同步问题。 比如两个线程同时操作一个DOM,那最终页面显示上以...
  • js为什么要有异步?

    2020-05-02 11:06:08
    异步不会阻塞代码执行,页面就不会卡住,所以使用异步 异步采用回调callback的形式 console.log(1) alert(2) // 页面会在这一行卡住 console.log(3) // 使用异步( 回调的形式 )处理上面问题 console.lo...
  •  有人问:为什么JS不能像CSS、image一样并行下载了?这里需要简单介绍一下浏览器构造页面的原理, 当浏览器从服务器接收到了HTML文档,并把HTML在内存中转换成DOM树,在转换的过程中如果发现
  • 嵌入JS会阻塞所有内容的呈现,而外部JS只会阻塞其后内容的显示 CSS 关于CSS,大家肯定都知道的是标签放在头部性能会高一点,少一点人知道如果css加载会阻塞DOM树的解析渲染吗? css阻塞 这是...
  • 然而,为什么呢?大家有考虑过么?很长一段时间,我问过不少团队里前端的开发人员,但实际得到的解释一塌糊涂,这里总结一下。 总结 CSS 不会阻塞 DOM 的解析,但会阻塞 DOM 渲染。 JS 阻塞 DOM 解析,但浏览器会&...
  • 有人问:为什么JS不能像CSS、image一样并行下载了?这里需要简单介绍一下浏览器构造页面的原理, 当浏览器从服务器接收到了HTML文档,并把HTML在内存中转换成DOM树,在转换的过程中如果发现某个节点(node)上引用...
  • 有人问:为什么JS不能像CSS、image一样并行下载了?这里需要简单介绍一下浏览器构造页面的原理,当浏览器从服务器接收到了HTML文档,并把HTML在内存中转换成DOM树,在转换的过程中如果发现某个节点(n...
  • 几种优化js在加载和执行过程中的方法。...为什么js加载和执行那么慢呢?这与js的阻塞特性有关。浏览器使用单进程处理 UI 更新和 JavaScript 运行等多个任务。脚本执行可能改变页面内容,因此...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 139
精华内容 55
关键字:

为什么js会阻塞页面