欢迎各位兄弟 发布技术文章
这里的技术是共享的
官方网站:http://stevesouders.com/controljs/
ControlJS能做什么:
先看两个示例页面:
下面的 使用了ContrloJs的页面 有大用
没有使用ControlJS的页面 | 使用了ControlJS的页面
下面三步有大用
怎样使用ControlJS:
要把ControlJS应用到您当前的页面中,只需修改三个部分的内容
#1:引入control.js文件
control.js本身会以异步的方式加载:
1 2 3 4 5 6 |
<script type="text/javascript"> var cjsscript = document.createElement('script'); cjsscript.src = "control.js"; var cjssib = document.getElementsByTagName('script')[0]; cjssib.parentNode.insertBefore(cjsscript, cjssib); </script> |
#2:修改页面中需要异步加载脚本的script标签的相关属性
页面中正常引入外部脚本是下面这样的格式:
1 |
<script type="text/javascript" src="main.js"></script> |
把script标签的TYPE属性改成“text/cjs”,SRC属性改成data-cjssrc,像下面这样:
1 |
<script type="text/cjs" data-cjssrc="main.js"></script> |
#3:修改内嵌脚本的script标签相关属性:
1 2 3 |
<script type="text/cjs"> var name = getName(); </script> |
ControlJS是怎样工作的?
ControlJS是通过什么方式让页面中的脚本可以无阻塞的下载执行?在上面的使用方法中你可能已经知道了他的运行方式。它是通过修改页面中 script标签的相关属性,让浏览器识别不了这是脚本文件,然后在页面中查找type属性为“text/cjs” 的script标签,让这些脚本文件以img(在IE和Opera中)或object(除IE和Opera的其他浏览器中)的方式下载,从而实现了无阻 塞,而且,因为这些脚本文件不是通过script标签下载的,它们在下载之后不会立即执行。
默认情况下,ControlJS是在window对象的onload事件里执行的(也可让它在脚本或某dom对象装载完就执行)。页面里的脚本会按 它出现的先后顺序执行。外部引入的脚本,一旦它伪装成的图片对象或OBJECT对象下载完成,便会以SCRIPT标签的形式嵌入到页面中去,这样这些脚本 就能被解析执行。
注:其实大多数情况下,把js文件放在页面底部完全能达到相同的效果,这里主要介绍的是他的一种实现方法。
这个与jQuery.getScript()有什么区别
@jason:getScript只是加载脚本,而ControlJS是控制这个过程。
@jason:getScript只是加载脚本,而ControlJS是控制这个过程。
+1
这种方式不会导致js报错me?
来自 http://www.rjboy.cn/?p=807
ControlJS - 让脚本加载的更快
前端性能的提升大部分都是在脚本加载执行上,ControlJS的出现让我们感觉 提高性能如此容易。急不可耐的想把这段时间的研究成果分享出来,希望能给前端俊才们些帮助,同样换回你们的批评指教。非常感谢拔赤师兄的有情支助,让我感 觉前端真是个很有乐趣的领域,因为你知道什么是有意义。
Steve Souders在2010年12月份发布了ControlJS项目,该项目是让开发者更好的去控制javascript文件的下载和执行,是一个可以让脚本加载更快的组件.从而解决了页面加载脚本的性能问题.
Steve提出了一个非常具有创造性的思想,就是预先异步下载javascript文件而不执行.这一点得到了很多人的关注与验证。Nicholas Zaka也因ControlJS引发了很多思考,并分析了ControlJS和LABjs 的区别所在,详细内容可以阅读Thoughts on script loaders和Separating JavaScript download and execution。Zakas不赞成使用额外的脚本加载库,因为Script loader对浏览器检测的依赖,将是高成本的维护,同时浏览器的发展趋势会为我们解决此类问题。
但 是对于中国互联网的特殊性来分析,脚本加载库的应用还是非常有必要的。很多ControlJS的思想让我们合理的应用,提升页面脚本加载性能将是非常显 著。Steve专门整理了ControlJS专题,包括一些实例,验证了ControlJS的成功,并使用3篇博闻详细介绍了ControlJS:异步加载、延迟执行、重写document.write。
1、异步加载
原 理其实很简单:将script的标签type属性值更改为浏览器无法识别的类型,这样浏览器不会认为这是一个脚本,便不会去下载文件。在页面加载时开始读 取所有type="text/cjs"的script标签(包括内嵌脚本),如果存在"DATA-CJSSRC"属性将创建IMAGE或者OBJECT对 象(依赖浏览器而选择),去异步下载脚本文件并缓存文件,否则便是内嵌脚本需要预存直到需要时使用eval执行,外链需要插入script元素,解析并执 行js内容。
a>增加ControlJS脚本
var
cjsscript = document.createElement(
'script'
);
cjsscript.src =
"control.js"
;
var
cjssib = document.getElementsByTagName(
'script'
)[0];
cjssib.parentNode.insertBefore(cjsscript, cjssib);
b>更改页面脚本标签属性
<script type=
"text/cjs"
data-cjssrc=
"main.js"
><script>
<script type=
"text/cjs"
>
var
name = getName();
<script>
c>预加载脚本的过程源码内容如下:
// Download a script as an image.
// This puts it in the browser's cache, but doesn't execute it.
CJS.downloadScriptImage =
function
(url) {
var
img =
new
Image();
img.src = url;
};
// Download a script as an object.
// This puts it in the browser's cache, but doesn't execute it.
// Based on http://www.phpied.com/preload-cssjavascript-without-execution/
CJS.downloadScriptObject =
function
(url) {
var
obj = document.createElement(
'object'
);
obj.data = url;
document.body.appendChild(obj);
};
2、延迟执行
预加载javascript文件后,在真正出发交互时在进行脚本的执行操作。
3、重写document.write
ControlJS 是异步加载所有脚本的,在默认情况下这些异步脚本都是在window.onload解析并执行的,如果此时脚本调用window.write方法,将导致 一个不希望发生的问题,就是整个页面被window.write的输出内容替换,所有页面内容将被删除。问题是由于在docuemnt被加载完后调用 docuemnt.write方法时将会自动去触发document.open,写入任何处于打开状态的doucment都将会会替换整个页面的内容,这是无可厚非的。
对于现在被开发者深恶痛绝的广告,一般都是使用document.write方法来呈现内容的,然而无法将这些内容异步处理是开发者非常头疼的问题。
ControlJS 的解决方法便是重写docuemnt.write,执行客户端自定义的方法,便是创建一个dom元素(span),将其插入正在被解析执行的script 标签之前,并且设置SPAN的innerHTML的值为docuemnt.write的内容。由于插入innerHTML里存在script标签时,浏览 器将不会很好的识别,因此ControlJS的做法是查找并提取出url,并在页面动态创建script对象来执行脚本内容。
但是ControlJS存在一个bug就是没有考虑到如果document.write中的script脚本中再次出现document.write的时候,将无法正确定位到最初的异步script,导致广告内容输出的位子错位。
以上便是ControlJS的相关内容,在实际项目的应用中肯定还会存在一些问题,就像Steve说的ControlJS虽然有些处理上牵强些,但它仍然是很有价值的,我们怎样能将别人的思想融入到我们自己的项目中才是最重要的,光靠拿来主义理论是没有任何意义的。
最后总结ControlJS为我们做了什么事:
1、异步下载所有脚本
2、同时处理内嵌与外链脚本
3、延迟脚本的执行直到页面被渲染完
4、允许脚本只下载不执行
5、不改变脚本代码,只是简单改变HTML标签属性
6、解决了异步脚本中存在docuement.write的问题
7、ControlJS本身是异步加载
关注 - 5
粉丝 - 9
» 下一篇:Flow view - 被忽视的性能检测,占96%的流量
来自 http://www.cnblogs.com/cheche/archive/2011/05/17/1982706.html
异步加载:ControlJS让脚本加载更快的一个模块
关于ControlJs一共有三篇文章,这是第一部分。ControlJS是让脚本加载更快的一个模块(a javascript module for making scripts load faster). 三篇文章的结构分别为:
1. async loading
2. delayed execution
3.overriding document.write
关 于第一部分的异步加载,这个的关键在于尽快将页面作为html绘制出来,然后再用javascript进行优化,或者说用js进一步渲染。我们看到过很多 网页,展示给用户一片空白,只是因为在等待几百KB的js文件下载、解析、执行,而这些js是用来绘制页面中展示给用户看的DOM元素。
其实上述的情况,很容易理解–但是真正实现改进恐怕就困难的多。好几百KB的js必须要拆散重组。那些通过js来创建网页DOM的逻辑代码必须全部合成到后台的服务器端去生成html。即使使用最新的服务器端JS来实现,也是一项很大的重构工程。
我又回到了Opera的Delayed Script Execution选项。一旦这个选项生效,js会被搁置起来(move aside),让页面首先进行渲染。而这个选项确实很棒,而且没有网站因为开启了这个选项而导致页面报错的。我也一直持续在和其他浏览器的供应商联系,让 他们也实现这个功能,我迫切的希望开发人员能够尽快的使用上这个选项。
近些年来,一些网页加速器(例如Aptimize, Strangeloop, FastSoft, CloudFlare, Torbit,和最近的mod_pagespeed)犹如雨后春笋般脱颖而出。他们修改了页面中的HTML标签,用来改善网页的性能。从这些模式中,我摸 索出了一个方法,比起延迟加载页面渲染的JS,我们可以更容易的改变HTML标记来实现。
于是ControlJS诞生了!
Controlling download and execution
ControlJS的目标是让开发员更好的控制JS的加载。关键是要意识到“加载”氛围两个步骤:下载[download](即获取内容)和执行[execution](包含解析).为了更好的性能,这两个步骤有必要分离控制。
在对网页性能敏感的程序员眼中,如何控制脚本下载是一个很广泛流行的话题。当脚本使用普通的方式(也就是<script src=”" …的形式),脚本会阻塞其他资源的下载(在新版本浏览器中稍微好一些),同时也会阻塞页面的渲染(所有浏览器都有这种情况)。使用异步脚本加载 (asynchronous script loading)的技术在很大程序上缓解了这个问题。我在Even Faster Web Sites中提及过几种异步加载的技术。LABjs 和 HeadJS是提供异步加载的js模块。虽然它们的异步技术解决了脚本下载阶段的阻塞问题,但是并没有解决脚本执行时发生的情况。
在脚本执行阶段,页面渲染和新资源下载会被阻塞。在如今网页中的脚本越来越多,在脚本执行阶段的阻塞问题就更为严重,尤其是在移动设备上。事实 上,Gmail移动设备组考虑到脚本执行带来的问题,它们完善了new async technique that downloads JavaScript wrapped in comments。这项技术可以使得脚本执行和下载分离。脚本会下载到客户端(在浏览器的缓存中),但是因为它是脚本注释,所以在执行阶段不会阻塞(因为 不会执行)。当用户使用了相关功能的时候,需要某些脚本时,会将注释符号删除,然后eval执行代码。
Stoyan Stefanov, 一名优秀的性能优化前驱者,最近发布了一篇博文preloading JavaScript without execution.他用IMAGE或者OBJECT(这取决于浏览器)来下载脚本。假设这些脚本可以缓存在客户端中,随后可以使用SCRIPT标签插入 脚本。这个也是在ControlJS中使用的技术。
ControlJS: how to use it
使用ControlJS涉及到三个步骤的修改
修改点#1:添加control.js
我想关于脚本加载模块的使用,最讽刺的地方就在于,加载这些异步脚本加载种子文件是会阻塞页面的。所以从一开始我就必须确认ControlJS是要能被异步加载的。
var cjsscript = document.createElement('script');
cjsscript.src = "control.js";
var cjssib = document.getElementsByTagName('script')[0];
cjssib.parentNode.insertBefore(cjsscript, cjssib);修改点#2:修改外链的脚本
下一步就是将所有外链脚本的标签改为ControlJS的形式。原本的脚本引用如下
<script type="text/javascript" src="main.js"><script>SCRIPT元素的TYPE要改为”text/cjs”,SRC改为“data-cjssrc”,如下:
<script type="text/cjs" data-cjssrc="main.js"><script>修改点#3 修改内联的脚本
大多数的页面都会有内联的脚本。这些脚本有一些依赖性:内联脚本中的变量一般依赖于外链的脚本,反之亦然。很重要的一点是:内敛脚本和外链脚本的执行顺序是需要保证的。因此,内联脚本必须改变TYPE属性的值
<script type="text/javascript">
var name = getName();
<script>修改“text/javascript”为”text/cjs”,如下:
<script type="text/cjs">
var name = getName();
<script>这样就ok了!后续的一系列工作就交给ControlJS担心吧!
ControlJS: how it works
现在脚本不会阻塞页面了,因为TYPE属性已经改为浏览器无法识别的值了。这也就让ControlJS可以用一种高性能的方法更好的控制脚本加载。让我们大概看看ControlJS是如何运作的呢?当然,你也可以查看control.js 的代码来更详细的了解。
我们都希望能够尽快的开始下载脚本。因为我们使用IMAGE或者OBJECT来下载脚本,所以它们不会在下载阶段阻塞页面。而且他们并不是作为 SCRIPT下载的,所以它们也不会执行。ControlJS首先找出所有SCRIPT的,并且type为”text/cjs”的标签。如果脚本有一个 DATA-CJSSRC,那么IMAGE(IE和Opera浏览器)或者OBJECT(其他浏览器)就会根据它们的URL动态的创建出来。(你可以查看 Stoyan’s post去了解更详细的内容)。
一般来说,ControlJS会在window load的时间之后进入执行阶段(当然也可以立刻执行代码或者某个DOM元素加载完毕了)。ControlJS会第二次遍历所有的脚本,确保它们都正确的 出现在页面中。如果这个脚本是一个内联脚本,那么它的代码会被执行。如果这个脚本是一个外链脚本,由IMAGE或者OBJECT动态下载下来的,那么它会 作为一个SCRIPT标签插入到页面中,那么它的代码也会随之解析并且执行。如果IMAGE或者OBJECT并没有下载结束,那么会在一个短暂的时间间隔 之后(a short timeout),重新进入刚才的遍历流程。
后续的文章中我还会讨论关于document.write的功能,以及跳过执行阶段。这篇中,我们首先来看一个简单的异步加载的例子。
Async example
为了能更好展示异步加载的情况,我创建了一个文件,文件顶部包含三个脚本:
•main.js – 耗费4秒下载
•一段内联脚本会使用main.js的一个变量
•page.js – 耗费2秒下载,使用内联脚本的一个变量
我 让page.js的下载时间比main.js的下载时间短,是为了确认这些脚本可以以正确的顺序执行(尽管page.js下载更快)。我同事也包含了内联 的脚本,因为这也是很多页面的实际情况(例如Google Analytics),但是很多脚本加载器并不支持内联脚本的执行顺序。
Async withOUT ControlJS是一个基本范例。它使用了最普通的方式加载脚本。可以看一下如下图所示的IE8下的HTTP瀑布图(使用HttpWatch).IE8 比IE6和IE7要好 – 能够使main.js和page.js并行加载。但是所有的IE都会因为脚本加载而阻塞图片的下载。所以images1-4都延迟了。在所有浏览器中,页 面渲染都会被阻塞。在图示中也可以看出,main.js阻塞渲染长达4秒钟(绿色的竖线表示页面开始渲染时间)
Async WITH ControlJS 演示了ControlJS是如何解决由于脚本引发的阻塞问题。不像上面的例子,脚本和图片会并行加载。同时页面渲染也是立刻开始的。如果你同时在浏览器中 演示这两个页面,你会发现ControlJS的页面会快很多。当然,你也发现在下面的图示中多了3个请求,一个是Control.js – 这个是用来异步加载脚本用的代码。另外两个请求时因为main.js和page.js下载了两次。第一次是使用IMAGE或者OBJCET下载,第二次是 使用SCRIPT标签加入页面用来执行代码的。因为main.js和page.js已经存在在浏览器缓存中了,所以他们不需要额外的下载时间。只是短暂的 缓存读取时间(也就是那两根很细的蓝色线)。
The ControlJS project
Only part1ControlJS是在Apache License下面的开源项目。你可以在ControlJS Google Code project中找到control.js的代码。关于它的讨论可以在ControlJS Google Group.关于上面提到的例子放在我的站点 ControlJS Home Page.我只在大多数的浏览器中测试了,如果要投入到大规模的产品环境中,请进行更详尽的测试。
这只是ControlJS的第一部分。目前看来似乎已经解决了所有问题了。如果我们只是需要异步加载,那么其他的一些 技术其实也已经实现了。不过我的目标是不能让脚本阻塞页面的渲染。我们就必须面临一个问题,如果处理document.write.另一个方面就是类似于 Gmail的移动组实现的- 下载脚本同时在执行阶段不会阻塞页面渲染。我们会在下面的两篇博文中详细分析。
来自 http://www.webjx.com/javascript/jsajax-31179.html