动态装载外部JavaScript脚本文件
当我们请求一个URL地址时,浏览器会从远程服务器装载各种所需的资源,如JavaScript、CSS、图片等。而在加载JavaScript时,常常会发生下面这种情况:
也就是说,当浏览器碰到Script标签时,会下载整个js文件,同时不会下载其它资源,包括其它的js文件。不过这句话也是“含水分的”,水分到底多大,我也不知道,具体得看我们所使用的浏览器种类以及对应的版本号。下面是IE8的情况,它会同时下载多个js文件以及CSS文件,而图片等内容则会被阻塞,这点与之前的认识稍有不同,IE8多多少少引入了一点点“并发”。
不管怎样,由于采用标签形式所定义的js文件下载会造成整个下载阻塞,所以很多人会把Script标签写在</body>之前,或者是采用动态脚本装载的方式以加快页面显示。其具体例子可以从下面图中看到:
把Script标签写在body标签前来提早显示整个页面,这个是比较容易理解的;而动态脚本装载,是利用js动态创建Script的DOM对象,然后把这个DOM对象添加到当前文档中,从而实现js文件装载,而这种装载的方式与标签所实现的装载方式不同之处就在于不会形成阻塞。
上述所说内容以及图片资源来自以下两篇文章。
http://www.stevesouders.com/blog/2009/04/27/loading-scripts-without-blocking/
具体的实现方法可以参考下面的代码(http://stackoverflow.com/questions/2803305/javascript-how-to-download-js-asynchronously):
- var require = function (scripts, loadCallback) {
- var length = scripts.length;
- var first = document.getElementsByTagName("script")[0];
- var parentNode = first.parentNode;
- var loadedScripts = 0;
- var script;
- for (var i=0; i<length; i++) {
- script = document.createElement("script");
- script.async = true;
- script.type = "text/javascript";
- script.src = scripts[i];
- script.onload = function () {
- loadedScripts++;
- if (loadedScripts === length) {
- loadCallback();
- }
- };
- script.onreadystatechange = function () {
- if (script.readyState === "complete") {
- loadedScripts++;
- if (loadedScripts === length) {
- loadCallback();
- }
- }
- };
- parentNode.insertBefore(script, first);
- }
- };
调用举例:
- require([
- "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js",
- "http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js",
- "http://ajax.googleapis.com/ajax/libs/yui/2.7.0/build/yuiloader/yuiloader-min.js"
- ], function () {
- console.log(jQuery);
- console.log($);
- console.log(YAHOO);
- });
上面的代码只是外部JavaScript非阻塞装载的一种方法,而http://www.stevesouders.com/blog/2009/04/27/loading-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.
虽然这些方案都可以实现无阻塞下载,但还有一点要记住,对于一个域来说浏览器所能打开的连接数是有限的,从下面链接可以找出一些相关的数据:
http://www.stevesouders.com/blog/2008/03/20/roundup-on-parallel-connections/
对于同一个域来说,连接个数是有限的,不过我们可以通过让一个页面引用多个域的资源以达到扩大连接数的目的。所以有时会发现有的Web应用将动态程序和静态的资源分到不同的应用当中。另外还有一种主动的方法,就是客户机主动设置浏览器的最大连接数:http://support.microsoft.com/?kbid=282402。对于IE6和7来说,默认的最大连接数是2,在做聊天室,使用“长轮询”作为解决方案时一定要多考虑考虑。
最后给出的几篇文章,是同一个作者不同时期的文章,其内容全是关于动态装载的,可以作为参考:
- http://www.nczonline.net/blog/2009/06/23/loading-javascript-without-blocking/
- http://www.nczonline.net/blog/2009/07/28/the-best-way-to-load-external-javascript/
- http://www.nczonline.net/blog/2010/12/21/thoughts-on-script-loaders/
- http://www.nczonline.net/blog/2011/02/14/separating-javascript-download-and-execution/
技术总是在更新换代,现在我们关注的问题可能几年之后就会变成老皇历了。因为新的HTML5标准中,可以在script(http://dev.w3.org/html5/spec/Overview.html#the-script-element)上使用defer和async属性了,如果再加上浏览器本身的技术与概念的进步和“摩尔定律”的鼓吹,三五年差不多够了。
动态装载外部JavaScript脚本文件的更多相关文章
- 动态引用外部的Javascript脚本文件[转]
你可以参考下面方法,进行动态为网页引用外部的Javascript脚本文件.代码写在Page_Init方法内. VB.NET: 下图是运行时,查看HTML的源代码: C#:
- 获取当前正在执行的Javascript脚本文件的路径
获取当前JavaScript脚本文件的路径,在特定场景下可能需要,比如写模块加载器,或者进行日志记录.下面这段脚本适用于所有浏览器来获取正在执行js文件的路径,但是该方法只适用于脚本加载过程中执行的情 ...
- 使用jQuery动态加载js脚本文件的方法
动态加载Javascript是一项非常强大且有用的技术.这方面的主题在网上已经讨论了不少,我也经常会在一些个人项目上使用RequireJS和Dojo加载js 它们很强大,但有时候也会得不偿失.如果你使 ...
- 对动态加载javascript脚本的研究
有时我们需要在javascript脚本中创建js文件,那么在javascript脚本中创建的js文件又是如何执行的呢?和我们直接在HTML页面种写一个script标签的效果是一样的吗?(关于页面scr ...
- MySQL执行外部sql脚本文件命令是报错:unknown command
使用source导入外部sql文件: mysql> source F:\php\bookorama.sql; -------------- source F: -------------- ER ...
- MySQL执行外部sql脚本文件的命令
sql脚本是包含一到多个sql命令的sql语句,我们可以将这些sql脚本放在一个文本文件中(我们称之为“sql脚本文件”),然后通过相关的命令执行这个sql脚本文件.基本步骤如下:1.创建包含sql命 ...
- django项目外部的脚本文件执行ORM操作,无需配置路由、视图启动django服务
#一.将脚本路径添加到python的sys系统环境变量里 import sys # sys.path.append('c:/Users/Administrator/www/mymac') #第一种.绝 ...
- MySQL执行外部sql脚本文件命令报错:unknown command '\'
由于编码不一致导致的 虽然大部分导出是没有问题的 但是数据表中存储包含一些脚本(富文本内容)会出现该问题,强制指定编码即可解决. mysql导入时指定编码: mysql -u root -p --de ...
- 浏览器环境下JavaScript脚本加载与执行探析之代码执行顺序
本文主要基于向HTML页面引入JavaScript的几种方式,分析HTML中JavaScript脚本的执行顺序问题 1. 关于JavaScript脚本执行的阻塞性 JavaScript在浏览器中被解析 ...
随机推荐
- Linux驱动之PCI
<背景> PCI设备有许多地址配置的寄存器,初始化时这寄存器来配置设备的总线地址,配置好后CPU就可以访问该设备的各项资源了.(提炼:配置总线地址) <配置寄存器> ( ...
- JS 常用库汇总收集
本文不定期更新, 用于汇总记录一些看着 ok 的 JS 库. 库名 简介 项目地址 macy.js 仅 4 kb的 原生 流布局插件 http://macyjs.com/ Driver.js 仅 4 ...
- 最短网络Agri-Net
[问题描述] 农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场.当然,他需要你的帮助.约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场. ...
- Educational Codeforces Round 45 (Div 2) (A~G)
目录 Codeforces 990 A.Commentary Boxes B.Micro-World C.Bracket Sequences Concatenation Problem D.Graph ...
- Codeforces Round #353 (Div. 2) A. Infinite Sequence 水题
A. Infinite Sequence 题目连接: http://www.codeforces.com/contest/675/problem/A Description Vasya likes e ...
- CSS选择器复习
通用选择器:* 选择到所有的元素 选择子元素:> 选择到元素的直接后代(第一级子元素) 相邻兄弟选择器:+ 选择到紧随目标元素后的第一个元素 普通兄弟选择器:~ 选择到紧随其后的所有兄弟元素 伪 ...
- 读书笔记_Effective_C++_条款三十八:通过复合塑模出has-a或者is-implemented-in-terms-of
如果说public是一种is-a的关系的话,那么复合就是has-a的关系.直观来说,复合就是在一个类中采用其他类的对象作为自身的成员变量,可以举个例子,像下面这样: class Person { pr ...
- 华为S5300系列交换机V100R006SPH017VRP热补丁
S5300_V100R006SPH017.pat 附件: 链接:https://pan.baidu.com/s/16lrNMykatXR3_5xKBc2zuw 密码:rt1l
- 7407 74LS07 74LV07 74LVC07
SN7407 Convert TTL Voltage Levels to MOS LevelsHigh Sink-Current CapabilityInput Clamping Diodes Sim ...
- More about STALL
http://fx.damasgate.com/more-about-stall/ In other USB classes, a sender can indicate the end of a t ...