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” 并在耦合异步脚本中提出一些可以做到这一点的方法。

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

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

    JavaScript,动态加载脚本和样式 一动态脚本 当网站需求变大,脚本的需求也逐步变大.我们就不得不引入太多的JS脚本而降低了整站的性能,所以就出现了动态脚本的概念,在适时的时候加载相应的脚本. ...

  2. 让浏览器非阻塞加载javascript的几种方式

    通常大多数浏览器是并行下载资源的,但由于外部脚本的特殊性例如通过脚本改变文档的DOM结构.脚本之间的存在依赖关系.使用document.write 向页面输出HTML等.浏览器为了确保正确执行脚本和呈 ...

  3. 高性能 js -- 无阻塞加载脚本

    参考: <<高性能JavaScript>> Nicbolas C. Zakas 著 javascript代码的下载和执行过程会阻塞浏览器的其他进程, 比如页面的绘制, 遇到&l ...

  4. JavaScript无阻塞加载具体方式

    将脚本放在底部.\还是放在head中,用以保证在js加载前,能加载出正常显示的页面.\<script>标签放在\前 成组脚本:由于每个\<script>标签下载时阻塞页面解析过 ...

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

    下面的图片是我使用firefox和chrome浏览百度首页时候记录的http请求 下面是firefox: 下面是chrome: 在浏览百度首页前我都将浏览器的缓存全部清理掉,让这个场景最接近第一次访问 ...

  6. 无阻塞加载和defer、async

    无阻塞加载 把js放在head里,浏览器是怎么去执行它的呢,是按顺序加载还是并行加载呢?在旧的浏览器下,都是按照先后顺序来加载的,这就保证了加载的js依赖不会发生问题.但是少部分新的浏览器已经开始允许 ...

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

    一.动态加载脚本 当网站需求变大,脚本的需求也逐步变大.我们就不得不引入太多的 JS 脚本而降低了整站的性能,所以就出现了动态脚本的概念,在适时的时候加载相应的脚本. 1.动态加载js文件 比如:我们 ...

  8. 高性能Javascript--脚本的无阻塞加载策略

    Javascript在浏览器中的性能,可以说是前端开发者所要面对的最重要的可用性问题. 在Yahoo的Yslow23条规则当中,其中一条是将JS放在底部 .原因是,事实上,大多数浏览器使用单进程处理U ...

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

    原文转自:http://blog.jobbole.com/78191/ Javascript在浏览器中的性能,可以说是前端开发者所要面对的最重要的可用性问题. 在Yahoo的Yslow23条规则当中, ...

随机推荐

  1. web自动化测试框架总结

    web自动化测试框架总结: https://www.processon.com/mindmap/5bdab924e4b0878bf41e9e09

  2. Java开发工程师(Web方向) - 01.Java Web开发入门 - 第3章.Tomcat

    第3章--Tomcat Tomcat安装与运行 Tomcat:目前最常用的基于java的web应用服务器 本课程中所有的Java代码最终都需要部署到Tomcat中运行 Tomcat的配置文件是XML的 ...

  3. lintcode101 删除排序数组中的重复数字 II

    删除排序数组中的重复数字 II   跟进“删除重复数字”: 如果可以允许出现两次重复将如何处理? 在:lintcode100删除排序数组中的重复数字 的基础上进行改进. class Solution ...

  4. yun rpm

    RPM:RedHat Package Manager的简称,是一种数据库记录的方式的管理机制.当需要安装的软件的依赖软件都已经安装,则继续安装,否则不予安装. 特点:1.已经编译并打包完成2.软件的信 ...

  5. LeetCode - 463. Island Perimeter - O(MN)- (C++) - 解题报告

    原题 原题链接 You are given a map in form of a two-dimensional integer grid where 1 represents land and 0 ...

  6. 解决python中文编码错误问题

    对于初学者而言,编码问题或许还没有没重视起来,但是编码问题是中文开发者必须面对的.今天来看下python开发中如何解决编码问题.注意:本篇讲的是最常见的一种编码问题,其他编码问题,如json函数引起的 ...

  7. ArrayList遍历(JAVA)

    假如有个ArrayList变量如下: ArrayList<String> list = new ArrayList<String>(); list.add("arra ...

  8. linux+Nginx+Mysql+PHP环境下,安装mysqli模块

    奶奶的腿儿啊,太不易了.倒腾了小半天儿,写此随笔,待后查. 阿里云ecs中,安装phpcms,出现了一个问题:环境检测的时候,一直提示 Mysqli扩展没开启. 老夫哪儿特么会这么专业的啊...能咋办 ...

  9. Ninject学习资料

    https://github.com/ninject/Ninject/wiki/Modules-and-the-Kernel http://www.cnblogs.com/willick/p/3223 ...

  10. C语言100例02 PHP版(练习)

    问题: 企业发放的奖金根据利润提成. 利润(I)低于或等于10万元时,奖金可提10%: 利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%: 20万到 ...