并行加载与顺序执行

Javascript文件(下面简称脚本文件)需要被HTML文件引用才能在浏览器中运行。在HTML文件中可以通过不同的方式来引用脚本文件,我们需要关注的是,引用的具体实现方式和这些方式可能会带来的性能问题。

首先,引用脚本必须用到<script>标签,所以需要了解<script>标签的特性,引述书中作者原话:

当浏览器遇到(即内嵌<script>标签时,当前浏览器无从获知Javascript是否会修改页面内容。因此,这时浏览器会停止处理页面,先执行Javascript代码,然后再继续解析和渲染页面。同样的情况也发生在使用 src 属性加在Javascript的过程中(即外链),浏览器必须先花时间下载外链文件中的代码,然后解析并执行它。在这个过程中,页面渲染和用户交互完全被阻塞了。

根据上述描述,能了解到:

每当浏览器解析到<script>标签(无论内嵌还是外链)时,浏览器会优先下载、解析并执行该标签中的Javascript代码,而阻塞了其后所有页面内容的下载和渲染。

可以说,正是因为<script>标签的这一特性,所以才有了脚本文件的各种引用方式及其讨论。

##传统做法

最传统的做法是在<head>标签内插入<script>标签:

<head>
	<script src="test.js"></script>
	<link rel="stylesheet" type="text/css" href="styles/test.css" />
</head>

这种引用方式隐藏着严重的性能问题。由于<script>标签的特性,当浏览器解析到<script>标签时,浏览器优先下载解析脚本文件,而停止解析其后的页面内容,这意味着,其后的 test.css 样式文件和<body>标签都无法被加载,由于<body>标签无法被加载,那么页面自然就无法渲染了。因此在该javascript代码完全执行完之前,页面都是一片空白。

下面用张动态图来说明:

上图有两点是需要注意的:

  • 页面的渲染和javascript代码的执行是一起显示出来的。

    说明最开始出现的空白正是由于javascript文件阻塞特性引起的。这是因为如果脚本文件没有阻塞页面渲染的话,页面的渲染一般要先于脚本文件的加载,简来说就是页面先显示出来,过一小会儿,才有动态效果(一般来说页面所需要的的css样式文件和html文件的体积会远远小于脚本文件,如果没有被阻塞,它们会先于脚本文件下载好,然后立即被浏览器解析出来)。

  • 图片的加载是在javascript执行之后才开始的

    说明javascript阻塞了图片的加载。

##推荐做法

既然<script>标签会阻塞其后内容的加载,那么将<script>标签放到所有页面内容之后不就可以避免这种糟糕的状况了吗?如下:

<body>

	<!-- 页面其他内容 -->

	<!-- 推荐的脚本放置位置 -->
	<script type="text/javascript" src="file1.js">
	<script type="text/javascript" src="file2.js">
	<script type="text/javascript" src="file3.js">
</body>

将所有的<script>标签尽可能地放到<body>标签底部,尽量避免对页面其余部分下载及渲染的影响,效果图如下:

对比上一张动态图,可以发现,页面渲染要先于脚本文件的执行,说明脚本文件不再阻塞页面渲染了(包括css文件和img等文件的下载)。

然而这种做法在一些老旧的浏览器中依旧有些弊端,先选取书中作者的原话:

(将脚本放到<body>标签底部时)尽管脚本下载会阻塞另一个脚本,但是页面的大部分内容已经下载完成并显示给用户…

也就是说,尽管在IE8+浏览器上已经实现了脚本并行下载,但在更老旧浏览器中,页面中脚本仍是一个接着一个加载的。就上面的示例代码而言,浏览器先加载完file1脚本文件,再去加载file2脚本文件,最后才轮到file3脚本文件。虽然此时脚本已经不阻塞其他页面内容,但脚本之间却是相互阻塞加载,于是有了动态加载脚本这一方法。

###动态加载 动态加载脚本文件,即通过文档对象模型(DOM),在页面任意地方创建并插入<script>标签:

var script=document.createElement(‘script‘);
script.type=‘text/javascript‘;
script.src=‘file1.js‘;
document.getElementsByTagName(‘head‘)[0].appendChild(script);

上述代码动态创建了一个链接file1脚本文件的<script>标签,并将其添加到<head>标签内。

这种方法的优点在于:

无论在何时启动下载,文件的下载和执行过程不会阻塞页面其他进程(包括脚本加载)。

然而这种方法也是有缺陷的:

脚本会在下载完成后立即执行,那么意味着多个脚本之间的运行顺序是无法保证的(除了Firefox和Opera)。

当某个脚本对另一个脚本有依赖关系时,就很可能发生错误了。

转载自:http://blog.lxjwlt.com/front-end/2013/05/17/loading-javascript.html

时间: 2024-10-26 15:25:36

并行加载与顺序执行的相关文章

js的并行加载与顺序执行

javaScript文件(下面简称脚本文件)需要被HTML文件引用才能在浏览器中运行.在HTML文件中可以通过不同的方式来引用脚本文件,我们需要关注的是,这些方式的具体实现和这些方式可能会带来的性能问题. 当浏览器遇到(内嵌)<script>标签时,当前浏览器无从获知javaScript是否会修改页面内容.因此,这时浏览器会停止处理页面,先执行javaScript代码,然后再继续解析和渲染页面.同样的情况也发生在使用 src 属性加在javaScript的过程中(即外链 javaScript)

js的并行加载以及顺序执行

重新温习了下这段内容,发现各个浏览器的兼容性真的是搞大了头,处理起来很是麻烦. 现在现总结下并行加载多个js的方法: 1,对于动态createElement('script')的方式,对所有浏览器都是异步并行加载的.这里所说的并行不仅仅指的是 js并行加载,也包括js和其他资源比如图片,iframe的加载.但是此种方式在Firefox的2.0 3.0 3.1版本和opera 9.63 下是可以顺序执行的.但是由于Kyle的提议,现代浏览器都可以通过对动态创建的script元素设置属性async=

head.js让网站并行加载但顺序执行JS

http://headjs.com/ 并行加载JS,但是执行的时候却按顺序执行,提高网站速度 <script src="js/head.min.js"></script> <script type="text/javascript"> head.js("js/jquery-1.6.1.min.js","js/jquery.validate.min.js","js/my_valida

LABjs学习(一)之无阻塞动态并行加载脚本文件以及管理执行顺序

什么是LABjs LABjs是一个动态的脚本加载器,LABjs的定义特性是能够在浏览器允许的范围内以最快的速度并行加载所有JavaScript文件,但是如果文件之间存在依赖关系,则可以选择确保正确的执行顺序. 总计来说就是:动态并行加载脚本文件以及管理加载脚本文件的执行顺序 使用方法 $LAB对象替代了<script>标签,然后.script()方法表示加载Javascript文件,不带参数的.wait()方法表示立即运行刚才加载的Javascript文件,带参数的.wait()方法也是立即运

js顺序加载与并行加载

前端优化过程中常提到js的加载方式,下面说下几种常用的加载方式: 1:head标签内插入<script>标签 <script type="text/javaScript" src="test.js"></script> 这是最常见的方法,但是这个方法有个最大的问题,就是当浏览器解析到<script>标签时,浏览器会停止解析其后的内容,而优先下载脚本文件,并执行其中的代码,是个阻塞的过程,这意味着,其后的test.css

Javascript在页面加载时的执行顺序【转】

一.在HTML中嵌入Javasript的方法 直接在Javascript代码放在标记对<script>和</script>之间 由<script />标记的src属性制定外部的js文件 放在事件处理程序中,比如:<p onclick="alert('我是由onclick事件执行的Javascript')">点击我</p> 作为URL的主体,这个URL使用特殊的Javascript:协议,比如:<a href="

浅谈Html的内容加载及JS执行顺序

同事跟我说他用jQuery取不到页面上隐藏元素input的值,他的html页面大概内容如下. <!DOCTYPE html> <html lang="zh"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <script type="text/javascript"

js中页面加载完成后执行的几种方式及执行顺序

在js和jquery使用中,经常使用到页面加载完成后执行某一方法.通过整理,大概是五种方式(其中有的只是书写方式不一样). 1:使用jQuery的$(function){}; 2:使用jquery的$(document).ready(function(){});前两者本质上没有区别,第1种是第2种的简写方式.两个是document加载完成后就执行方法. 3:使用jQuery的$(window).load(function(){}); 4:使用window.onload = function(){

jquery.ready可以在文档加载后尽快执行对文档的操作

jquery 1.12.4中ready的关键代码 1 jQuery.ready.promise = function( obj ) { 2 if ( !readyList ) { 3 4 readyList = jQuery.Deferred(); 5 6 // Catch cases where $(document).ready() is called 7 // after the browser event has already occurred. 8 // Support: IE6-1