转自:http://www.cnblogs.com/huangxincheng/archive/2011/12/04/2275988.html

前言

最近研究MongoDB数据库,无意间发现的好博客,这位兄弟的博客,我很喜欢,适合入门,风格简约,大有同道中人之感......闲话少叙,入正题

内容(作者的例子是aspx格式的,读者改为了html格式,各位看官观花的时候注意一下)

做前端开发少不了各种利器。比如我习惯用的还是Google浏览器重型武器Fiddler

一. 原始情况

首先大家看看如下的代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="head">
<meta charset="UTF-8">
<title>test</title>
   <link href="Styles/Site.css" rel="stylesheet" type="text/css" />
   <script src="jquery/jquery-1.4.1.js" type="text/javascript"></script>
   <script src="js/hello.js" type="text/javascript"></script>
   <script src="js/world.js" type="text/javascript"></script>
</head>
<body>
<img src="1.jpg" width="" height="" />
</body>
</html>

估计90%的程序员都会把js文件放在head中,但是大家有没有深究过呢?

  很多浏览器都会使用单一的线程来做“界面UI的更新”和“JS脚本的处理“,也就是当执行引擎遇到”<script>“的时候,此时页面的下载和渲染都必须等待<script>执行完毕。那么对用户而言就悲哀了,看着锁住的页面,此时用户很可能就会给你关掉。

从上面的瀑布图中我们可以看出二点:

第一. 三个js文件并行下载,但是按我上面的理论中js应该是一个接一个的执行。然而在IE8,Firefox3.5和Chrome2都实现了js的并行下载,

这是相当不错的,但是他还是会阻碍一些其他资源的下载,比如说图片。

第二. 图片1.jpg的下载是在js执行完成后触发的,这也验证了上面所说的情况,阻止了image的加载。

二. 第一步优化

既然js阻止了UI渲染,那么我们可以考虑将js放在</body>前,这样就可以让<script>前的html完美的呈现,不会让用户看到页面空白等待

而苦恼的情况,自然就提高了友好性。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="head">
<meta charset="UTF-8">
<title>test</title>
<link href="Styles/Site.css" rel="stylesheet" type="text/css" />
</head>
<body>
<img src="1.jpg" width="" height="" />
<script src="jquery/jquery-1.4.1.js" type="text/javascript"></script>
<script src="js/hello.js" type="text/javascript"></script>
<script src="js/world.js" type="text/javascript"></script>
</body>
</html>

下面的图也展示了1.jpg和三个js几乎并行下载和执行。时间由上面的“469ms+”缩小到“326ms”。

三. 第二步优化

看上面的“瀑布图”,估计大家也看出来了,三个js文件进行了三次“Get”请求,大家都知道Get请求是需要带http头的,

所以说需要耗费时间,那么我们采取的方案自然就是减少Get请求,通常有两种方案。

第一:合并js文件,比如将上面的“hello.js"和“world.js“合并掉。

第二:利用第三方工具,比如php中的Minify。

关于第二种做法,taobao用的还是比较多的,看一下其中的一个script,应用了三个js文件。由3个Get请求变为了1个。

四. 第三步优化

不管是把js文件放在脚尾,还是三个合并一个,其本质都是”阻塞模式“,就是说锁死浏览器,当web页面越来越复杂,js文件越来越多,还是

让我们头疼的,此时我们就提倡一种“无阻塞模式“加载js脚本,也就是页面全部呈现完再追加js,也就对应着window.onload事件触发后,我们才

追加js,这就是所谓的“无阻塞“,但是其中有一个非常要注意的地方就是我们对js的要求是否有严格的顺序。

第一. 无顺序要求,比如我对”hello.js“和”world.js"没有顺序要求,那么我们完全可以用jquery来动态追加实现。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="head">
<meta charset="UTF-8">
<title>test</title>
<link href="Styles/Site.css" rel="stylesheet" type="text/css" />
</head>
<body>
<img src="1.jpg" width="" height="" />
<script src="jquery/jquery-1.4.1.js" type="text/javascript"></script>
<script type="text/javascript">
window.onload = function () {
$("#head").append("<script src='js/hello.js' type='text/javascript'><\/script>");
$("#head").append("<script src='js/world.js' type='text/javascript'><\/script>");
}
</script>
</body>
</html>

从图中可以看出,"hello.js"和“world.js"出现在蓝色线以后,也就说明这两个js是在DomContentLoad结束后再进行触发加载的,这样就不会造成页面的锁定等待。

第二. 有顺序要求

为什么一定要有顺序要求这个概念呢?

对于上面的那个动态追加的“两个js”文件,在IE系列中,你不能保证hello.js一定会在world.js前执行,他只会按照服务器端返回的顺序执行代码。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="head">
<meta charset="UTF-8">
<title>test</title>
<link href="Styles/Site.css" rel="stylesheet" type="text/css" />
</head>
<body>
<img src="1.jpg" width="" height="" />
<script type="text/javascript">
function loadScript(url, callback) {
var script = document.createElement("script");
script.type = "text/javascript"; //IE
if (script.readyState) {
script.onreadystatechange = function () {
if (script.readyState == "loaded" || script.readyState == "complete") {
script.onreadystatechange = null;
callback();
}
}
} else {
//非IE
script.onload = function () {
callback();
}
}
script.src = url;
document.getElementById("head").appendChild(script);
}
//第一步加载jquery类库
loadScript("jquery/jquery-1.4.1.js", function () {
//第二步加载hello.js
loadScript("js/hello.js", function () {
//第三步加载world.js
loadScript("js/world.js", function () { });
});
});
</script>
</body>
</html>

大家也能看到,页面完全Load的时间其实也就310ms左右,大大提高了网页的下载呈现和友好型。

同样也可以看看腾讯网,他也是这么干的。

读者:

确实学到了些东西,之前对这方面没有具体的概念,受益了受益啦......

Javascript加载执行问题探索的更多相关文章

  1. Javascript加载执行顺序

    本文主要内容 一.不同位置的script标签执行顺序 二.document.ready和window.onload的区别 一.不同位置的script标签执行顺序 整个加载的过程从解析头部开始,比如ht ...

  2. 使用async属性异步加载执行JavaScript

    HTML5让我兴奋的一个最大的原因是,它里面实现的新功能和新特征都是我们长久以来一直期待的.比如,我以前一直在使用placeholders,但以前必须要用JavaScript实现.而HTML5里给Ja ...

  3. HTML5特性:使用async属性异步加载执行JavaScript

    HTML5让我兴奋的一个最大的原因是,它里面实现的新功能和新特征都是我们长久以来一直期待的.比如,我以前一直在使用placeholders,但以前必须要用JavaScript实现.而HTML5里给Ja ...

  4. 怎么样加快JavaScript加载和执行效率

    概览 无论当前 JavaScript 代码是内嵌还是在外链文件中,页面的下载和渲染都必须停下来等待脚本执行完成.JavaScript 执行过程耗时越久,浏览器等待响应用户输入的时间就越长.浏览器在下载 ...

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

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

  6. javascript加载顺序

    javascript加载顺序 <script type="text/javascript" src="jquery.js"></script& ...

  7. ArcGIS api for javascript——加载查询结果,悬停显示信息窗口

    转自原文 ArcGIS api for javascript——加载查询结果,悬停显示信息窗口 描述 本例在开始和地图交互前执行一个查询任务并加在查询结果.这允许用户鼠标悬停在任意郡县时立即见到Inf ...

  8. JSBinding + SharpKit / JavaScript 加载流程

    首先,现在的方案是游戏启动就加载全部的 JavaScript 代码. 先看下 StreamingAssets/JavaScript/ 文件夹下的目录结构:

  9. Javascript加载速度慢解决办法

    通常我们的网站里面会加载一些js代码,统计啊,google广告啊,百度同盟啊,阿里妈妈广告代码啊,一堆,最后弄得页面加载速度很慢,很慢.解决办法:换一个js包含的方式,让javascript加载速度倍 ...

随机推荐

  1. VS2013中修改.dll工程项目的.lib和.dll的输出路径

    一个dll工程,生成的两个东西是我们需要的:.lib和.dll,在实际开发过程中我们往往希望这两个东西直接输出到特定文件夹,对于这两个的修改: 设置好之后,对于调用该dll的exe工程,将exe的输出 ...

  2. Python【基础第三篇】

    set集合 s1=set() 集合特点: 访问速度快 没有重复项 collections系列(数据类型容器模块) 一.计数器(Counter) Counter是对字典类型的补充,用于追踪值的出现次数. ...

  3. FlatBuffers要点

    FlatBuffers发布出来一周多,周末便抽时间先研究下它的使用方法.Flatbuffers的idl的语法主要参考[http://google.github.io/flatbuffers/md__s ...

  4. Python:类属性,实例属性,私有属性与静态方法,类方法,实例方法

    From: http://www.cnblogs.com/pengsixiong/p/4823473.html 属性分为实例属性与类属性 方法分为普通方法,类方法,静态方法 一:属性: 尽量把需要用户 ...

  5. IOS列表实现动态多列

    . //图片列表 NSMutableArray *pictureList; //分组列表 NSMutableArray *indexArr; - (UITableViewCell *)tableVie ...

  6. 分布式文件系统--GFS

    分布式文件系统 分布式文件系统:当数据集的大小超过一台独立物理计算机的存储能力时,就有必要对它进行分区(partition)并存储到若干台单独的计算机上.管理网络中夸多台计算机存储的文件系统.这种系统 ...

  7. linux which 查看可执行文件的位置

    我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索:        which  查看可执行文件的位置.       whereis 查看文件的位置.         ...

  8. OpenSSL命令---ciphers

    用途: 指令是用来展示用于SSL加密算法的工具.它能够把所有openssl支持的加密算法按照一定规律排列(一般是加密强度).这样可以用来做测试工具,决定使用什么加密算法. 用法: openssl ci ...

  9. 字符编解码的故事(ASCII,ANSI,Unicode,Utf-8)

    很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物.他们认为8个开关状态作为原子单位很好,于是他们把这称为"字节". 再后来,他们又做了一 ...

  10. git 安装与使用场景

    1. 安装 yum install git #自动安装依赖 centos sudo apt-get install git #ubutu http://msysgit.github.io/ #wind ...