外部JS的阻塞下载

转载于: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

时间: 2024-10-09 16:23:54

外部JS的阻塞下载的相关文章

app端开发中,外部js是否需要下载到本地,到负载均衡

再一次app开发中,发现有引用的外部文件: 外部的文件不是应该下载到本地然后在引用这样不是更安全吗?(当时的心声)于是咨询了下经验丰富的同事: 引用外部的js文件时,优先使用非常快的CDN(Content Delivery Network 网络之上的内容分发网络,使客户端可以访问最近的边缘服务器,实现更快的加载,降低了网络阻塞,提高用户的访问响应速度). 假设,首次进入app index.html:index.js;css 等文件为1M ,需要加载的外部js等文件有6M.如果服务器的带宽很小,哪

02 详解主流浏览器多个外部JS请求和执行机制

在IE8.Firefox3.6之前页面加载外部的javascript文件(IE6和IE7会连同图片,样式资源和页面渲染一同阻塞)是阻塞式的,而在之后的版本中,浏览器都使用了瀑布式加载,这样页面的打开及渲染速度都会变快,请注意,我提到的瀑布式加载,仅仅指的是加载,而非JS的执行,在主流浏览器中JS的执行总是阻塞的.用简单一点的语言描述,就是同一时间,页面只会加载一个js文件.在第一个js文件加载并执行完之前,第二个要引入的js不会下载和执行.而页面中js的引入顺序以请求的顺序为定. 我们来看一个在

javascript中外部js文件取得自身完整路径得办法

原文:javascript中外部js文件取得自身完整路径得办法 有时候我们需要引入一个外部js文件,这个js文件又需要用到自己的路径或者是所在的目录,别问怎么又这么变态的需求,开发做久了各种奇葩需求也就有了! 有人第一时间想到的是location.href,可是哥哥,那个引用页面的路径啊.比如a.html: <html> <script src="/b/c.js"></script> </html> 这样的话我们用location.hre

为什么要采用外部js文件

这篇文章主要讲的是为什么要采用外部js文件,有什么好处. 为什么不把js内嵌在html中呢,这样不是好分析吗?对,这样你是好分析,同样的别人呢?不内嵌在html中有如下原因:   安全性: 只要查看页面的源代码,任何人都可以确切的知道其中的代码做了什么.如果怀有恶意的开发者查看了源代码,就可能发现安全漏洞,危机整个站点或应用程序的安全.此外,在外部文件中还可以加入版权和其他知识产权通告,而不打断页面流 代码维护: 如果javascript代码散布于多个页面,那么代码维护将变成异常噩梦.把所有ja

vue如何导入外部js文件(es6)

也许大家都是使用习惯了es5的写法喜欢直接用<Script>标签倒入js文件,但是很是可惜,这写法.在es6,或则说vue环境下不支持 真的写法是怎样? 首先.我们要改造我们要映入的外部js文件,改成下面这个格式.主要是红色方块内部代码,我们需要将我们的模块"抛出",让人能获取到 代码: [html] view plain copy function realconsole(){ alert("hello.thanks use me"); } expor

kettle转换JavaScript加载外部js文件

日常开发中,时常会出现这样一种情况.有大量的函数是通用的.而每个JavaScript里面写一遍,给维护带来很大的困扰.因而需要将公共的函数写在外部js文件中.这时就需要引入外部的公共文件了.下面是在转换里的JavaScript组件中引入外部公共js文件. //加载js文件 LoadScriptFile(getVariable("Internal.Transformation.Filename.Directory", "") +"/common_Functi

webBrowser调用外部js文件和js函数(转载)

原文链接:http://fy5388.blog.163.com/blog/static/56499537201012594314130/ webBrowser调用外部js文件和js函数 '第一种方法:webbrowser动态调用html和js代码,都是动态的:代码示例: webBrowser1.Navigate("about:blank");webBrowser1.Document.OpenNew(True);webBrowser1.Document.Write("<H

JS中单引号/双引号以及外部js引入的一些问题

一.单引号和双引号的用法的问题 在JavaScript中可以使用单引号.双引号,二者也可以混合使用.但是,身为菜鸟的我,却碰到了一些引号的使用问题. <body> <div style="border:1px solid red; height:150px;width:150px;" onclick="alert("test");" id="test">This is a test. </div&

js防阻塞加载

<script type="text/javascript"> function scriptDomElement (u) { var s = document.createElement('script'); h = document.getElementsByTagName('body')[0]; s.src = u; s.async = true; if(h)h.appendChild(s,h.firstChild); } scriptDomElement('http