JavaScript非阻塞加载脚本

As more and more sites evolve into “Web 2.0″ apps, the amount of JavaScript increases. This is a performance concern because scripts have a negative impact on page performance. Mainstream browsers (i.e., IE 6 and 7)  block in two ways:

  • Resources in the page are blocked from downloading if they are below the script.
  • Elements are blocked from rendering if they are below the script.

随着越来越多的网站涉及“Web 2.0”应用,JavaScript脚本的数量也急剧增加。这是令人忧虑的,因为脚本对页面性能有负面影响。主流的浏览器(例如IE 6 、7)会以下面2种方式发生阻塞:

  • 如果资源位于脚本的下方,那么他们会被阻塞下载。泌阳县马奇建材
  • 如果元素位于脚本的下方,那么他们会被阻塞渲染展示。

The Scripts Block Downloads example demonstrates this. It contains two external scripts followed by an image, a stylesheet, and an iframe. The HTTP waterfall chart from loading this example in IE7 shows that the first script blocks all downloads, then the second script blocks all downloads, and finally the image, stylesheet, and iframe all download in parallel. Watching the page render, you’ll notice that the paragraph of text above the script renders immediately. However, the rest of the text in the HTML document is blocked from rendering until all the scripts are done loading.

这个脚本阻塞下载的例子(Scripts Block Downloads example) 展示了上面的情况。它包括2个外部脚本,后面是1个图片、1个样式表和1个iframe。使用IE7加载这个例子的HTTP瀑布图显示了第一个脚本阻塞了所有的下载,随后第2个脚本阻塞了所有的下载,最后图片样式表和iframe并行加载。观察页面的渲染情况,你会发现脚本上方的那段文字会马上渲染。然而,HTML 文档其它部分的文字会被阻塞,直到所有的脚本被下载完毕。

在 IE6 7, Firefox 2 3.0, Safari 3, Chrome 1, Opera 脚本均会阻塞下载

Browsers are single threaded, so it’s understandable that while a script is executing the browser is unable to start other downloads. But there’s no reason that while the script is downloading the browser can’t start downloading other resources. And that’s exactly what newer browsers, including Internet Explorer 8, Safari 4, and Chrome 2, have done. The HTTP waterfall chart for the Scripts Block Downloads example in IE8 shows the scripts do indeed download in parallel, and the stylesheet is included in that parallel download. But the image and iframe are still blocked. Safari 4 and Chrome 2 behave in a similar way. Parallel downloading improves, but is still not as much as it could be.

如果浏览器是单线程的,那么当一个脚本在执行时,浏览器不能下载其它资源是可以理解的。但是没有理由解释当脚本下载时浏览器不能下载其它资源。下载脚本的同时并行下载其它资源是所有最新浏览器的已经实现了的功能,包括Internet Explorer 8, Safari 4, Chrome 2。在IE8中打开脚本阻塞下载的例子(Scripts Block Downloads example)的HTTP瀑布图展示了脚本确实是并行下载的,样式表也是并行下载的,然而图片和iframe仍旧被阻塞了。Safari 4 和 Chrome 2 的行为也很类似。并行下载改善了一部分,但还没有达到它能达到的最好的效果。

IE8, Safari 4, Chrome 2下,脚本仍旧是阻塞的

Fortunately, there are ways to get scripts to download without blocking any other resources in the page, even in older browsers. Unfortunately, it’s up to the web developer to do the heavy lifting.

幸运的是,即使在更老的浏览器中,也有使脚本不阻塞其它页面资源的办法。不幸的是,这取决于web开发人员是否愿意承担这些繁重的工作。

There are six main techniques for downloading scripts without blocking:

  • XHR Eval – Download the script via XHR and eval() the responseText.
  • XHR Injection – Download the script via XHR and inject it into the page by creating a script element and setting its text property to the responseText.
  • Script in Iframe – Wrap your script in an HTML page and download it as an iframe.
  • Script DOM Element – Create a script element and set its src property to the script’s URL.
  • Script Defer – Add the script tag’s defer attribute. This used to only work in IE, but is now in Firefox 3.1.
  • document.write Script Tag – Write the <script src=""> HTML into the page using document.write. This only loads script without blocking in IE.

下面有6种非阻塞式加载脚本的技术:

  • XHR Eval - 通过XHR下载脚本,通过eval()执行。
  • XHR Injection - 通过XHR下载脚本,通过创建一个script的DOM元素注入页面,并且设置text属性。
  • Script in Iframe - 在一个HTML页面内包含脚本并通过iframe加载。
  • Script DOM Element - 创建一个script的DOM元素,并且设置src属性为脚本的url。
  • Script Defer - 增加脚本的defer属性。曾经仅在IE中可用,现在Firefox 3.1. 中也可以了。
  • document.write Script Tag - 在HTML页面内使用document.write <script src="">。仅在IE有效。

You can see an example of each technique using Cuzillion. It turns out that these techniques have several important differences, as shown in the following table. Most of them provide parallel downloads, although Script Defer and document.write Script Tag are mixed. Some of the techniques can’t be used on cross-site scripts, and some require slight modifications to your existing scripts to get them to work. An area of differentiation that’s not widely discussed is whether the technique triggers the browser’s busy indicators (status bar, progress bar, tab icon, and cursor). If you’re loading multiple scripts that depend on each other, you’ll need a technique that preserves execution order.

在Cuzillion你可以看到每个技术的样例。事实证明这些技术有重要的区别,见下面表格。它们大部分提供并行下载,有些技术不能被使用在跨域名的脚本上,有些必须在你已有的脚本基础上简单的修改,还有一个未被广泛讨论的是否触发浏览器的繁忙指示标记区别(状态栏,进度条,标签图标和光标)。如果你需要加载多个相互依存的脚本,你还需要一个维护执行顺序的技术。

技术名称 支持并行下载 支持跨域名 不需修改脚本 是否有繁忙指示 保障执行顺序 大小(字节)
XHR Eval IE, FF, Saf, Chr, Op no no Saf, Chr - ~500
XHR Injection IE, FF, Saf, Chr, Op no yes Saf, Chr - ~500
Script in Iframe IE, FF, Saf, Chr, Op no no IE, FF, Saf, Chr - ~50
Script DOM Element IE, FF, Saf, Chr, Op yes yes FF, Saf, Chr FF, Op ~200
Script Defer IE, Saf4, Chr2, FF3.1 yes yes IE, FF, Saf, Chr, Op IE, FF, Saf, Chr, Op ~50
document.write Script Tag IE, Saf4, Chr2, Op yes yes IE, FF, Saf, Chr, Op IE, FF, Saf, Chr, Op ~100

The question is: Which is the best technique? The optimal technique depends on your situation. This decision tree should be used as a guide. It’s not as complex as it looks. Only three variables determine the outcome: is the script on the same domain as the main page, is it necessary to preserve execution order, and should the busy indicators be triggered.

问题是:哪个是最好的技术?最佳的技术取决于您的具体情况。下面这个决策树可以作为一个指导。它看起来复杂,其实并不是。只有3个参数就决定了输出结果:脚本是否在主页面的同一个域名之下,是否需要保障执行顺序,是否需要触发繁忙指示标记。

Ideally, the logic in this decision tree would be encapsulated in popular HTML templating languages (PHP, Python, Perl, etc.) so that the web developer could just call a function and be assured that their script gets loaded using the optimal technique.

最理想的是,这个决策树的逻辑将体现在流行的HTML模板语言中(PHP, Python, Perl, 等),因此WEB开发人员可以简单的调用一个函数,就能保证他们的脚本使用最佳的技术来加载脚本。

In many situations, the Script DOM Element is a good choice. It works in all browsers, doesn’t have any cross-site scripting restrictions, is fairly simple to implement, and is well understood. The one catch is that it doesn’t preserve execution order across all browsers. If you have multiple scripts that depend on each other, you’ll need to concatenate them or use a different technique. If you have an inline script that depends on the external script, you’ll need to synchronize them. I call this “coupling” and present several ways to do this in Coupling Asynchronous Scripts.

很多情况下,使用 Script DOM Element是一个不错的选择。它可以在所有浏览器下工作,没有任何跨域限制,代码上很容易实现,很容易被理解,唯一不足的是并不是在所有浏览器下均能保持正确的执行顺序。如果你有多个脚本并且相互依赖,你需要合并他们或使用其它技术。如果你在页面内有依赖于外部脚本的内联脚本,你必须对他们实现同步化,我将这个方法称为“coupling” 并在耦合异步脚本中提出一些可以做到这一点的方法。

时间: 2024-08-04 20:34:19

JavaScript非阻塞加载脚本的相关文章

前端性能之非阻塞加载js脚本

SCRIPT标签的阻塞行为会对页面的性能产生影响,这是因为浏览器在下载脚本.解析.执行的过程中不会同时做其他事情,比如渲染页面.响应用户事件等.之所以这样做是因为正在执行的JavaScript代码可能会改变页面元素.修改样式.添加或者删除事件等各种操作,以及最关键的脚本之间的依赖性,浏览器必须等待当前执行的脚本执行完成之后再进行后续操作. 脚本阻塞 两种加载方式 HTML页面中的JavaScript脚本有两种方式加入 - 使用script标签内联到HTML页面,页面按从上到下的顺序执行到scri

无阻塞加载脚本

一个页面,从被请求访问,到用户可以看到页面.操作页面,到最后页面完全加载完毕,中间需要经历一个相当奇幻的过程,这个过程的速度被"web性能师"孜孜不倦.前赴后继的优化.本文讨论的是其中一个优化. 浏览器线程和阻塞 虽然大家耳熟能详的一句话是: JavaScript是单线程的. 但是: 浏览器当然不是单线程的. 浏览器的多线程中,有的线程负责加载资源,有的线程负责执行脚本,有的线程负责渲染界面,有的线程负责轮询.监听用户事件. 这些线程,根据浏览器自身特点以及web标准等等,有的会被浏览

第一百一十八节,JavaScript,动态加载脚本和样式

JavaScript,动态加载脚本和样式 一动态脚本 当网站需求变大,脚本的需求也逐步变大.我们就不得不引入太多的JS脚本而降低了整站的性能,所以就出现了动态脚本的概念,在适时的时候加载相应的脚本. 比如:我们想在需要检测浏览器的时候,再引入检测文件. 1动态加载js文件 window.onload = function() { //window.onload事件,等待html执行完成后,执行匿名函数 //判断要加载的文件是否加载成功 alert(typeof BrowserDetect); }

无阻塞加载脚本的方案

1.动态加载脚本 <script type="text/javascript"> function loadScript(url){ var script=document.createElement("script"); script.type="text/javascript"; script.src=url; document.body.appendChild(script); } loadScript("js/sid

无阻塞加载脚本,按序执行

通常加载页面的时候,对于组件是并行下载的,现代大部分浏览器对于Js同样也是支持并行下载,但是在脚本下载.解析并执行完毕之前,不会开始下载任何其他内容. 正常引入: 可以看出,在脚本下载完毕后的一段时间内(该时间在解析执行脚本),不会对其他组件进行下载,以下几种方案解决该问题. 1. XHR Eval加载脚本: 即使用ajax引入脚本,并通过eval对其执行. 代码: var xhrObj = getXHRObject(); xhrObj.onreadystatechange = function

探真无阻塞加载javascript脚本技术,我们会发现很多意想不到的秘密

原文:探真无阻塞加载javascript脚本技术,我们会发现很多意想不到的秘密 下面的图片是我使用firefox和chrome浏览百度首页时候记录的http请求 下面是firefox: 下面是chrome: 在浏览百度首页前我都将浏览器的缓存全部清理掉,让这个场景最接近第一次访问百度首页的情景. 在firefox的请求瀑布图里有个表现非常之明显:就是javascript文件下载完毕后,有一段时间是没有网络请求被处理的,这段时间过后http请求才会接着执行,这段空闲时间就是所谓的http请求被阻塞

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

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

JavaScript的DOM_动态加载脚本和样式

一.动态加载脚本 当网站需求变大,脚本的需求也逐步变大.我们就不得不引入太多的 JS 脚本而降低了整站的性能,所以就出现了动态脚本的概念,在适时的时候加载相应的脚本. 1.动态加载js文件 比如:我们想在需要检测浏览器的时候,再引入检测文件. <script type="text/javascript"> window.onload = function(){ alert(typeof BrowserDetect); } var flag = true; //设置 true

【转】高性能Javascript--脚本的无阻塞加载策略

原文转自:http://blog.jobbole.com/78191/ Javascript在浏览器中的性能,可以说是前端开发者所要面对的最重要的可用性问题. 在Yahoo的Yslow23条规则当中,其中一条是将JS放在底部 .原因是,事实上,大多数浏览器使用单进程处理UI和更新Javascript运行等多个任务,而同一时间只能有一个任务被执行.Javascript运行了多长时间,那么在浏览器空闲下来响应用户交互之前的等待时间就有多长. 从基本层面说,这意味着<script>标签的出现使整个页