高性能web开发 如何加载JS,JS应该放在什么位置?


Posted in Javascript onMay 14, 2010

外部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个下载)。
高性能web开发 如何加载JS,JS应该放在什么位置?
嵌入JS的阻塞下载
嵌入JS是指直接写在HTML文档中的JS代码。上面说了引用外部的JS会阻塞其后的资源下载和其后的内容呈现,哪嵌入的JS又会是怎样阻塞的了,看下面的列2个代码:
代码1:

<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>

代码2(test.zip里面的代码与代码1的JS代码一模一样):
<div> 
<ul> 
<li>blogjava></li> 
<li>CSDN></li> 
<li>博客园></li> 
<li>ABC></li> 
<li>AAA></li> 
<ul> 
<div> 
<script type="text/javascript" src="test.zip"><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="https://3water.com/images/logo.gif" /><</span>br /> 
<img src="http://csdnimg.cn/www/images/csdnindex_piclogo.gif" /> 
</body> 
</html>

时间瀑布图:
高性能web开发 如何加载JS,JS应该放在什么位置?
代码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="https://3water.com/images/logo.gif" /><</span>br />
<img src="http://csdnimg.cn/www/images/csdnindex_piclogo.gif" />
</body>
时间瀑布图:
高性能web开发 如何加载JS,JS应该放在什么位置?
从时间瀑布图中可以看出,代码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

[声明] 转载请注明出处:http://www.blogjava.net/BearRui/。 禁止商用!

Javascript 相关文章推荐
JavaScript实现横向滑出的多级菜单效果
Oct 09 Javascript
深入浅析JSON.parse()、JSON.stringify()和eval()的作用详解
Apr 03 Javascript
总结十个Angular.js由浅入深的面试问题
Aug 26 Javascript
纯JS焦点图特效实例(可一个页面多用)
Dec 07 Javascript
weex slider实现滑动底部导航功能
Aug 28 Javascript
EL表达式截取字符串的函数说明
Sep 22 Javascript
JavaScript中重名的函数与对象示例详析
Sep 28 Javascript
Vue开发Html5微信公众号的步骤
Apr 11 Javascript
使用Phantomjs和Node完成网页的截屏快照的方法
Jul 16 Javascript
Vue elementui字体图标显示问题解决方案
Aug 18 Javascript
Vue在H5 项目中使用融云进行实时个人单聊通讯
Dec 14 Vue.js
jquery自定义组件实例详解
Dec 31 jQuery
js 图片等比例缩放代码
May 13 #Javascript
跨浏览器开发经验总结(四) 怎么写入剪贴板
May 13 #Javascript
跨浏览器开发经验总结(三)   警惕“IE依赖综合症”
May 13 #Javascript
JavaScript prototype属性使用说明
May 13 #Javascript
js 实现复制到粘贴板的功能代码
May 13 #Javascript
js href的用法
May 13 #Javascript
解决IE下select标签innerHTML插入option的BUG(兼容IE,FF,Opera,Chrome,Safari)
May 13 #Javascript
You might like
深入PHP magic quotes的详解
2013/06/17 PHP
解析php入库和出库
2013/06/25 PHP
PHP上传文件时文件过大$_FILES为空的解决方法
2013/11/26 PHP
如何解决PHP无法实现多线程的问题
2015/09/25 PHP
javascript打开新窗口同时关闭旧窗口
2009/01/16 Javascript
jQuery温习篇 强大的JQuery选择器
2010/04/24 Javascript
JavaScript的parseInt 取整使用
2011/05/09 Javascript
基于JQuery的类似新浪微博展示信息效果的代码
2012/07/23 Javascript
使用jquery的ajax需要注意的地方dataType的设置
2013/08/12 Javascript
js调用打印机打印网页字体总是缩小一号的解决方法
2014/01/24 Javascript
JavaScript使用Math.Min返回两个数中较小数的方法
2015/04/06 Javascript
jquery实现的用户注册表单提示操作效果代码分享
2015/08/28 Javascript
JS实现黑色风格的网页TAB选项卡效果代码
2015/10/09 Javascript
jquery ajax局部加载方法详解(实现代码)
2016/05/12 Javascript
jQuery插件form-validation-engine正则表达式操作示例
2017/02/09 Javascript
jquery实现自定义树形表格的方法【自定义树形结构table】
2019/07/12 jQuery
详解微信小程序自定义组件的实现及数据交互
2019/07/22 Javascript
微信小程序中的video视频实现 自定义播放按钮、封面图、视频封面上文案
2020/01/02 Javascript
JavaScript享元模式原理与用法实例详解
2020/03/09 Javascript
使用beaker让Facebook的Bottle框架支持session功能
2015/04/23 Python
详解Python中表达式i += x与i = i + x是否等价
2017/02/08 Python
Python tkinter模块弹出窗口及传值回到主窗口操作详解
2017/07/28 Python
python通过ffmgep从视频中抽帧的方法
2018/12/05 Python
Django实现简单网页弹出警告代码
2019/11/15 Python
django 实现celery动态设置周期任务执行时间
2019/11/19 Python
python中property和setter装饰器用法
2019/12/19 Python
tensorflow转换ckpt为savermodel模型的实现
2020/05/25 Python
使用html5实现表格实现标题合并的实例代码
2019/05/13 HTML / CSS
美国最大的农村生活方式零售店:Tractor Supply Company(TSC)
2017/05/15 全球购物
TripAdvisor日本:全球领先的旅游网站
2019/02/14 全球购物
销售代表求职自荐信
2013/10/01 职场文书
培训自我鉴定
2014/01/31 职场文书
爱国主义演讲稿
2014/05/07 职场文书
学生未请假就回家检讨书
2014/09/22 职场文书
领导干部“四风”查摆问题个人整改措施
2014/10/28 职场文书
Python实现数据的序列化操作详解
2022/07/07 Python