转载自:http://www.blogjava.net/BearRui/archive/2010/04/08/web_performance_js_where.html

外部JS的阻塞下载

所有浏览器在下载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: 
<</span>div>

        ul>
            li>blogjavaspan style="color: #800000;">li>
            li>CSDNspan style="color: #800000;">li>
            li>博客园span style="color: #800000;">li>
            li>ABCspan style="color: #800000;">li>
            li>AAAspan style="color: #800000;">li>
        ul>    
    span style="color: #800000;">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());
     }
    span style="color: #800000;">script>
  div>
        ul>
            li>MSNspan style="color: #800000;">li>
            li>GOOGLEspan style="color: #800000;">li>
            li>YAHOOspan style="color: #800000;">li>
        ul>    
    span style="color: #800000;">div>

代码2(test.zip里面的代码与代码1的JS代码一模一样):

div>
        ul>
            li>blogjavaspan style="color: #800000;">li>
            li>CSDNspan style="color: #800000;">li>
            li>博客园span style="color: #800000;">li>
            li>ABCspan style="color: #800000;">li>
            li>AAAspan style="color: #800000;">li>
        ul>    
    span style="color: #800000;">div>
    script type="text/javascript" src="http://www.blogjava.net/Files/BearRui/test.zip">span style="color: #800000;">script>
  div>
        ul>
            li>MSNspan style="color: #800000;">li>
            li>GOOGLEspan style="color: #800000;">li>
            li>YAHOOspan style="color: #800000;">li>
        ul>    
    span style="color: #800000;">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 testspan style="color: #800000;">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" />
            span style="color: #800000;">head>
            body>
                img src="http://www.blogjava.net/images/logo.gif" /><</span>br />
                img src="http://csdnimg.cn/www/images/csdnindex_piclogo.gif" />
            span style="color: #800000;">body>
            span style="color: #800000;">html>

时间瀑布图:
  

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

 head>
    title>js testspan style="color: #800000;">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(){}
  span style="color: #800000;">script>
    span style="color: #800000;">head>
    body>
        img src="http://www.blogjava.net/images/logo.gif" /><</span>br />
        img src="http://csdnimg.cn/www/images/csdnindex_piclogo.gif" />
    span style="color: #800000;">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来调用

非阻塞方式下载js方式:

  1.为<script>标签添加defer属性(只适用于IE和firfox 3.5以上版本)

  2.动态创建<script>标签,用它来下载并执行代码

  3.用xhr对象下载代码,并注入到页面中

高性能js之js加载执行的更多相关文章

  1. 高性能JS笔记1——加载执行

    一.脚本位置 1.Script标签尽可能放到Body底部,以减少脚本文件下载对整个页面UI渲染的影响. 2.Script标签永远不要紧跟Link标签后面. 二.组织脚本 1.合并多个文件在一个Scri ...

  2. 动态加载JS文件,并根据JS文件的加载状态来执行自己的回调函数

    动态加载JS文件,并根据JS文件的加载状态来执行自己的回调函数, 在很多场景下,我们需要在动态加载JS文件的时候,根据加载的状态来进行后续的操作,需要在JS加载成功后,执行另一方法,这个方法是依托在加 ...

  3. 对于HTML页面中CSS, JS, HTML的加载与执行过程的简单分析

    来自   https://blog.csdn.net/u011088260/article/details/79563315   最近在研究HTML页面中JavaScript的执行顺序问题.在Java ...

  4. JS,Javascript加载与函数执行过程

    Js,Javascript加载与函数执行过程 test.html <!DOCTYPE HTML> <html lang="en"> <head> ...

  5. 高性能js之js文件的加载与解析

    随着网站的发展,现在的网页已经离不开js,经常一个页面会引入大量的js.那么该如何合理的加载这些js? head标签中引入js文件可能是最常见的一种方式,但是这样会造成一个问题.因为j可以说是浏览器中 ...

  6. js jquery 页面加载初始化方法

    js jquery 页面加载初始化方法 一.js页面加载初始化方法 // 1.在body里面写初始化方法. <body onload='init()'> </body> < ...

  7. js的动态加载、缓存、更新以及复用(四)

    本来想一气呵成,把加载的过程都写了,但是卡着呢,所以只好在分成两份了. 1.页面里使用<script>来加载 boot.js . 2.然后在boot.js里面动态加载 bootLoad.j ...

  8. 关于js css html加载顺序整理

    1.js放在head中会立即执行,阻塞后续的资源下载与执行.因为js有可能会修改dom,如果不阻塞后续的资源下载,dom的操作顺序不可控. 正常的网页加载流程是这样的. 浏览器一边下载HTML网页,一 ...

  9. js优化 ----js的有序加载

    说到有序加载,我们先来说说js的无序加载: <script src="jquery/jquery-1.4.1.js" type="text/javascript&q ...

  10. JS/CSS/IMG加载顺序关系之DOMContentLoaded事件

    DOMContentLoaded介绍 DOMContentLoaded事件的触发条件是: 将会在“所有的DOM全部加载完毕并且JS加载执行后触发”. 但如果“js是通过动态加载进来的话,是不会影响到D ...

随机推荐

  1. Android 设计模式

    简介 项目开发中发现问题.解决问题这个过程中会出现很多问题,比如重复出现.某个问题的遗留,这些问题的本质就是设计模式.今天记录设计模式的知识点. 内容 在java以及其他的面向对象设计模式中,类与类之 ...

  2. (转) ASCII码对应表chr(9)、chr(10)、chr(13)、chr(32)、chr(34)、chr(39)、chr(

    chr(9) tab空格       chr(10) 换行      chr(13) 回车        Chr(13)&chr(10) 回车换行       chr(32) 空格符      ...

  3. [磁盘管理与分区]——MBR破坏与修复

    GURB的破坏和恢复(利用备份体恢复) (1)备份 # count= //对MBR中的引导程序部分作备份 (2)破坏MBR中的前446字节 # count= (3)恢复MBR中前446字节 ===&g ...

  4. 团队项目的NABC(截图软件)

    我们小组要开发的软件是基于windows上的截图软件,其NABC如下. 1.need: 首先,截图工具是几乎每个用户都会用到的,不管是在工作中,还是在学习上,其针对的人群从学生到上班族不等, 所以,他 ...

  5. android 通过httpclient下载文件并保存

    代码:(主要针对图片.gif下载无问题) /** * 下载网络文件 * @param url 请求的文件链接 * @param IsMD5Name 是否MD5加密URL来命名文件名 * @param ...

  6. 网页数据采集 - 系列之Flash数据采集

    经常看到一些朋友在讨论如何采集flash中的数据,讨论来讨论区,结论就是:flash不能采集,其实也不总是这样.本篇就跟大家分享如何采集flash中的数据. 在开始之前,先说明一下:一般来说flash ...

  7. 《Soft Skill》一书中的好句子

    The biggest mistake that you can make is to believe that you are working for somebody else. Job secu ...

  8. cygwin chmod 失效

    问题背景 为了在 Cygwin 下使用之前最喜爱的 screen 命令, 安装 Cygwin 时就选上了 screen 来运行一把 ganiks.liu@MAMIS-Gaiks-Liu /tmp $ ...

  9. 【BZOJ】【1863】【ZJOI2006】trouble 皇帝的烦恼

    二分+DP Orz KuribohG 神题啊= = 满足单调性是比较显然的…… 然而蒟蒻并不会判断能否满足……QwQ 神一样的DP姿势:f[i]表示第 i 个与第1个最多有多少个相同,g[i]表示最少 ...

  10. ios UI实现技巧

    statusBar 移动位置 NSString *key = [[NSString alloc] initWithData:[NSData dataWithBytes:(unsigned ] enco ...