setImpl
2013-04-03T11:47:58+08:00
http://jayli.github.com/
Jayli
bachi@taobao.com
第七届D2-移动设备Web开发最佳实践
2012-07-09T00:00:00+08:00
urn:uuid:0597dfb0-02c0-40e1-82f8-176b6dc31c8a
<div style="width:510px" id="__ss_13546648"> <object id="__sse13546648" width="510" height="420"> <param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=webv2-0-120704231324-phpapp01&rel=0&stripped_title=web-13546648&userName=lijing00333" /> <param name="allowFullScreen" value="true"/> <param name="allowScriptAccess" value="always"/> <param name="wmode" value="transparent"/> <embed name="__sse13546648" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=webv2-0-120704231324-phpapp01&rel=0&stripped_title=web-13546648&userName=lijing00333" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="transparent" width="510" height="420"></embed> </object></div>
<p>非常感谢圆心的盛情邀请,今年7月有幸参加了第七届D2前端技术论坛,和完颜一起做了这次'移动web开发最佳实践'的分享,今年前端的新话题有不少,除了'基础设施建设'、'第三方广告脚本'等话题之外,就是'移动终端开发'了,半年来淘宝在移动终端开发上有不少的项目和沉淀,一直在积极探索新模式新思路,有了一些经验和教训,总结下来分享给大家。</p>
<p>移动终端越来越火,呈现出一种井喷的态势,看下我们身边多少人在学习移动app的开发就知道火爆程度了。而且几乎是瞬间,书架就摆满了ios和android的应用开发的书籍。而我们的关注点则有所不同,当前互联网成千上万的页面,能否稍加改动就能优雅的运行于移动设备?在我们基于浏览器的项目开发中,有没有可能将PC终端的产品略作调整,就适应移动设备?我们这次分享的主题即是聚焦在这一方面,"让我们的网页更优雅的展现于移动终端"。</p>
<p>这个分享分为实现和优化,优化是非常重要的一块内容,因为优化直接影响到性能,影响用户体验的基础。我们甚至成立了一个虚拟小组来专门提炼这套最佳实践"响应式设计小组"。而就在刚刚,淘宝移动版也发布了新版本(http://m.taobao.com),之中加入了不少性能优化的部分,于是就有了这个ppt,我们也希望将尽可能多的信息量整理到ppt中,为大家的移动设备web开发给出一些启发。</p>
<p>PPT地址:<a href="http://www.slideshare.net/lijing00333/web-13546648">http://www.slideshare.net/lijing00333/web-13546648</a></p>
“JavaScript Web Applications” 译者序
2012-02-02T00:00:00+08:00
urn:uuid:60d35626-d0a1-441f-9815-5a38142eeb3c
<p><img src="http://img01.taobaocdn.com/tps/i1/T1YBC9XjJwXXXXXXXX-275-364.png" alt="" /></p>
<blockquote><p>经过将近半年的努力,我和好友一舟共同翻译的 <a href="http://jayli.github.com/jswebapps">JavaScript Web Applications</a> 这本书终于快要和大家见面了,近年来鲜有讲JavaScriptMVC的中文资料,这本书正好填补了这方面的空白,推荐大家一读。</p></blockquote>
<h3>译者序</h3>
<p>从第一眼看到封面这只憨憨的猫头鹰开始,就深深的喜欢上了这本“JavaScript Web Applications“,读了简介和目录之后就已经不能自拔了。这几年鲜有深入讲架构级web app的好书,这让这本“JavaScript Web Applications“更加难得,作为O'rielly第一本专注于讲纯高端JavaScript架构思想的书,凡是有一点“架构情节“的工程师都不应当错过此书。</p>
<p>如今Web应用程序的开发已经越来越向传统应用软件开发靠拢了,Web和应用之间的界限也进一步模糊。传统编程语言中的设计模式、MVC、应用架构等理论也在慢慢的融入Web前端开发。随着服务器端JavaScript和移动终端的兴起,作为一名前端工程师,也深知自己正处在一个深刻变革的年代,面对眼花缭乱的新概念和新技术更应当把握本质认清方向,勇于创新和实践,而这本“JavaScript Web Applications”的出现更是一阵及时雨,为我们工作中遇到的很多难题提供了解决方案和最佳实践。同时,这本书所涵盖的知识点非常全面,从MVC 的基本理论到网络协议、从模块解偶到异步编程模型、从HTML5/CSS3到NodeJS、从软件测试到部署调试,对于很多前端工程师来说,这些知识正是突破自己的瓶颈所亟需的。</p>
<p>这本书将专注于讲述如何构建“优雅又不失高水准”(state of the art)的JavaScript应用,包括软件架构、模板引擎、框架和库、同服务器的消息通信等内容。书中同样提供了大量的示例代码,可以帮助你更深入的理解很多重要的概念。除此之外,作者在MVC和架构方面的很多观点都很有启发性,即使你不是一名JavaScript程序员,读完本书后也会受益匪浅的。</p>
<p>本书作者 Alex MacCaw 是一名Ruby/JavaScript 程序员,是Spine框架的开发者。在翻译本书的过程中,我深深体会到他作为一名优秀工程师所具备的扎实的计算机专业功底和让人敬佩的开源精神。尽管这本书包含大量的专业术语,但作者文笔轻松流畅,即使直接读原文也丝毫不会感觉枯燥,所以我们在翻译过程中也是非常小心,生怕丢掉这种轻松流畅的阅读感觉,尽力为大家原汁原味的呈现本书。当然由于专业知识所限,翻译过程难免疏漏,还希望各位高手批评指正。</p>
<p>最后,我要感谢博文视点的张春雨在译书过程中给予我们的帮助和信任。感谢我的好友王保平(玉伯)对很多关键的技术性问题提出的宝贵意见,还要感谢可爱的同事杨振楠(栋寒)、杨翰文(地极)、李燕青(霸先)、车思慧(灵玉)、陈良(舒克)的细心校对,他们给译文提了很多中肯的建议。当然,最最需要感谢的家中的领导,已经记不得多少次赶译稿加班太晚,得到的不是你的抱怨,而是你的鼓励,心里已经觉得很满足。</p>
<p>李晶(拔赤),张散集(一舟)</p>
<p>2012年02月 北京</p>
YUISlide,针对移动设备的动画性能优化
2011-12-23T00:00:00+08:00
urn:uuid:c16ed91c-567b-4700-9398-2dc2834b1fee
<p><a href="http://jayli.github.com/gallery/yuislide">YUISlide</a>这是一个集选项卡切换和幻灯切换功能于一体的小插件,基于YUI3实现,之前主要用在普通的PC终端里,在<a href="http://wt.taobao.com/">网厅</a>项目中灵玉同学对Slide进行了改进,增加了手持设备里的小功能,比如手指滑动事件。但Slide的动画在移动端的表现出人意外的糟糕。</p>
<p>在普通的PC平台里,动画的实现大都是通过setInterval函数来完成,jQuery和YUI以及Kissy中亦是如此,只不过帧频有所差异。后来都各自添加了对内置css3 transition的检测,优先使用css3 animation,动画在现代浏览器中的性能又上升了一个台阶。Slide使用了YUI的Anim,在iphone/ipad/android平台中使用的是css3 animation,却依然不流畅,更流畅的动画则需要开启webkit的硬件加速。可以参照之前的一个<a href="http://www.slideshare.net/lijing00333/graphic-programming-in-js">ppt</a>来了解js动画编程的一些背景知识。</p>
<p>首先要清楚css3的transitions和transform有着细微的差别,css3 transform本质上是将元素的内容作平移,而非直接对元素作属性渐变,因此性能更好,通过Demo可以看出,移动端的Dom操作性能要比css3 animation慢几个数量级。因此要在Slide运行当中尽量减少Dom操作,因此这里对Slide里的跑马灯的实现原理做了微调,即在初始化的时候就处理好待用的Dom节点,而不用在每次执行next()时剪切Dom节点。</p>
<p><img src="http://jayli.github.com/gallery/yuislide/assets/slide-c.png" alt="" /></p>
<p>另外还有一个css3动画相关属性就是keyframe,这个是用来辅助作复杂动画时用的,通过设定关键帧来作动画,Slide中的简单动画暂时用不到。因此css3动画的几个属性小结如下:</p>
<ul>
<li>css3 transition:平滑的改变CSS属性值,和setInterval原理类似,但速度更快</li>
<li>css3 2d transform:二维变换,CSS属性值未渐变,未用到webGL加速,速度有提升,但提升程度有限</li>
<li>css3 3d transform:三维变换,CSS属性值未渐变,开启WebGL加速,速度明显提升</li>
<li>css3 animation:即使用keyframe来模拟动画,用来实现复杂动画,和性能无关</li>
</ul>
<p>判断是否开启内置动画:</p>
<pre><code>// true:支持,false:不支持
var nativeTransition =
"webkitTransition" in document.body.style;
</code></pre>
<p>在支持transition的平台中使用translate3d来启用webGL进行硬件加速,注意这里使用transform代替了transition:</p>
<pre><code>animNode.setStyles({
'-webkit-transition-duration': speed + 's',
'-webkit-transform':'translate3d('+dic+',0,0)'
});
</code></pre>
<p>最后比较下改造前和改造后的Slide在移动终端里的性能,在Ipad/Iphone中打开下面这两个Demo:</p>
<p>改造前,使用css3 2d transform(性能糟糕):<a href="http://jayli.github.com/gallery/yuislide/slide2.html">Demo</a>
改造后,使用css3 3d transform(动画流畅):<a href="http://jayli.github.com/gallery/yuislide/slide.html">Demo</a></p>
<p>Slide项目首页:<a href="http://jayli.github.com/gallery/yuislide/slide.html">http://jayli.github.com/gallery/yuislide/</a></p>
JavaScript Autoload 的实现
2011-06-09T00:00:00+08:00
urn:uuid:ae17bef1-8663-43b0-9333-bbdf67130116
<iframe src='http://www.slideshare.net/slideshow/embed_code/8590158' width='500' height='410' border=0></iframe>
<p>熟悉PHP的同学一定对autoload不会陌生。我们知道,不管在任何语言和类库中,要使用某个类(或者方法)的前提是这个类必须存在,这个类或方法可能在类库的某个文件的某个角落中定义了,但当类库太过庞大时,初学者往往记不起某个方法属于哪个文件,或者不知道类库文件存放在哪里。另外,开发者不知道什么时候需要用到这个文件,特别是项目文件特别多时,不可能每个文件都在开始的部分写很长一串require。PHP5中提供了__autoload来解决这个问题。开发者将注意力完全放在程序逻辑上,大胆的使用基础类和方法,而不必考虑类和方法属于哪个模块、如何将模块require进来、何时require比较合适,是否有多余的require等等。PHP程序会对代码作分析,自动将程序中用到的“陌生的类和方法”所属的库文件引入进来,保证程序的正确执行。这就是autoload的基本机制,Ruby和Python中也实现了这种机制。</p>
<p>autoload听起来不错,非常适于初学者,而且是动态语言必不可少的组成部分(我才不要像写Java或C++那样一本正经的纠结于程序定义了哪些变量、都是什么类型、作用域是什么、用了哪些类库、类库的引用关系是什么……)。</p>
<p>现在我们在JavaScript中实现PHP的这种autoload机制,其中实现的难点在于对代码的静态分析,这里所指的静态分析只是伪分析(除非嵌入一个JavaScript解释器)。看下在<a href="http://github.com/jayli/sandbox">Sandbox</a>中实现的autoload:</p>
<p>Demo:http://jayli.github.com/sandbox/examples/autoload/main.html</p>
<p>首先像PHP一样定义一个全局函数__autoload,返回值是一个map,给出每个方法对应的文件::</p>
<pre><code>function __autoload() {
return {
'MyClass1':'MyClass1.js',
'A.B.C.D':'MyClass1.js',
'MyClass2':'MyClass2.js',
'X.Y.Z':'MyClass2.js'
};
}
</code></pre>
<p>然后在沙箱中就可以随意使用定义好的类和方法了,和PHP的写法唯一的不同之处在于,PHP需要手写include方法来“阻塞式”引入文件,Sandbox只给出映射表即可,另外,Sandbox也不支持给__autoload传入参数,比如<code>__autoload($class_name)</code>。</p>
<pre><code>Sandbox.ready(function(S){
MyClass1.init();
MyClass2.init();
A.B.C.D.init();
});
</code></pre>
<p>具体实现可参见<a href="http://github.com/jayli/sandbox">sandbox-seed.js</a>源码</p>
<p>另外需要注意的一点是,看起来这里载入文件是“阻塞式”的,没错,逻辑的执行总是在载入文件完成后再执行,后端语言几乎都是阻塞式的引入文件,比如php中:</p>
<pre><code>//logic1...
include('file.php')
//logic2...
</code></pre>
<p>程序必然在file.php载入完成后再执行logic2,这就是所谓阻塞式载入外部文件,在服务器端的JavaScript中也是如此,比如CommonJS规范中定义的require方法,也是默认require的文件是“阻塞式”载入的,即requries时主程序“停止执行”,在载入文件结束后再继续执行。而在客户端JavaScript中是无法实现这种阻塞式载入外部文件的(有人提出可以用同步ajax来模拟载入外部脚本,但这涉及到跨域),在SeaJS中同样存在这个问题,玉伯给出的解决办法和Sandbox一样,都是对代码作过滤,都是一种“伪”阻塞,比如SeaJS中执行:</p>
<pre><code>define(function(require) {
return;
require('./a');
});
</code></pre>
<p>这段代码同样引入“./a.js”,而从逻辑上看是不应该引入这个文件的,Sandbox亦存在同样问题。</p>
<p>还需要注意一点,“阻塞式”加载的缺点就是串行,当然这是符合逻辑的,上下两个外部文件的引用必定有依赖关系,所以他们的执行不得不串行,Sandbox中加载多个脚本的实现也是串行,比如:</p>
<pre><code>Sandbox.loadScript(['a.js','b.js'],callback);
</code></pre>
<p>由于无法对a.js和b.js的内容作任何假设,因此串行一定是最安全的,也是唯一的策略,如果所有文件都有统一的约定,比如Sandbox中的Sandbox.add(callback)、YUI的YUI.add(‘name’,callback)、以及SeaJS中的define(callback),则多脚本加载有太多可优化的空间,比如YUI提供的comboCDN、以及SeaJS提供的build工具。</p>
<p>那么,JavaScript中什么时候适合使用autoload呢?应当是在做全站架构时最适合使用,由专人负责维护通用功能和组件,维护一份<code>__autoload</code>函数即可,当然,子逻辑可以重写这个函数(函数劫持),只要在页面中引用了种子文件就会包含这个<code>__autoload</code>函数,共用功能和组件就可以任意使用而不用刻意引入“包名”。也就是说,组件名称本身就是一个标识,这个标识和它所在的文件地址是一一对应的,根本不必再知晓组件名称属于哪个包名,这也符合autoload机制的本意。</p>
<p>当然这种做法有一个不足就是性能问题,这也是YUI为什么一定要将“包名”以及包的依赖预先定义好的原因。尽管从纯粹程序逻辑的角度讲,这样做是多余的。由于前端代码的性能依赖于网速,不像后端代码,因此在JavaScript中也应当有节制的使用autoload,切不可滥用,寻找架构代码可维护性和性能之间的平衡点,这一点非常重要。</p>
[翻译]F2E大会上关于@font-face的分享
2011-05-01T00:00:00+08:00
urn:uuid:b9234a49-4d30-421e-95b3-1d9c9ffe6aac
<ul>
<li>原文:http://www.nczonline.net/blog/2011/04/05/lessons-on-font-face-from-the-f2e-summit/</li>
<li>标题:Lessons on @font-face from the F2E Summit</li>
<li>作者:NCZakas</li>
<li>译文:F2E大会上关于@font-face的分享</li>
</ul>
<p>上周我参与组织了Yahoo F2E大会,这次大会聚集了Yahoo全球各地的前端工程师,其中@font-face是本次大会最受关注的话题之一,我们讨论了它的种种优势和缺陷,好记性不如烂笔头,我得赶紧把这些知识点记录下来,本篇内容来自于 Matt Seeley 关于“yahoo.com/tablet”的专题分享“iPad版Yahoo首页实战”(Lessons from the Tablet Front Page),以及来自于Adam Wang关于面向未来的CSS3的专题分享“无名小站新版首页案例分析”(Case Study:
Wretch New Front Page),在这里我只是将他们的分享做了摘录。</p>
<p>兼容性</p>
<p>如果你不清楚<code><video></code>和<code><audio></code>标签的兼容性问题的话,你可能也不会知道 @font-face 的兼容性情况,尽管在桌面浏览器中可以通过 OpenType、TrueType 和 WOFF 可以比较好的做到兼容,但在移动终端则没办法轻易做到兼容。iOS4.1 和较早的版本只支持 SVG 字体,而 Android 只支持 TrueType 字体。iOS4.2 及后续版本开始同时支持 OpenType、TrueType 和 SVG 字体。也就是说,要想兼容 iOS 和 Android,只要将 css 代码精简成如下模样即可:</p>
<pre><code>@font-face {
font-family: "Gotham Medium";
font-weight: normal;
font-style: normal;
src: url(gothmed.ttf) format(truetype),
url(gothmed.svg#id) format(svg);
}
</code></pre>
<p>也许这还不是最糟的,毕竟兼容性问题不止这么简单,因为在 IE9 中,src 属性不支持多值定义。比如上段代码会被错误的解析成:</p>
<pre><code>@font-face {
font-family: "Gotham Medium";
font-weight: normal;
font-style: normal;
src: url(gothmed.ttf)%20format(truetype),%20url(gothmed.svg#id)%20format(svg);
}
</code></pre>
<p>看到没,整个 src 属性被 URL 转码。也就是说在 IE8 及以下版本的浏览器中,将会发起一个类似这个 URL 的请求:</p>
<pre><code>/gothmed.ttf)%20format(truetype),%20url(gotmed.svg
</code></pre>
<p>我们看到#之后的字串被当成 URL 的 hash 部分,并不参于组成 HTTP 请求地址。这样的话,每次浏览页面都会造成一个404的请求。因此尽管在早期版本的IE中不支持src的多值定义,依然会发起一个 HTTP 请求。</p>
<p>为了解决这个问题,Matt 使用了 dataURI 来代替 TTF 字体文件,这样在IE8及更早版本的浏览器中就不会再发请求了。Matt 同样提及 dataURI 并不能代替 SVG 字体,因为 dataURI 的长度在 iOS 中受到了限制。</p>
<p>意外情形</p>
<p>Matt 同样指出了给 SVG 字体定义 text-overflow: ellipsis 样式时的意外情形,其他字体的这种样式定义是没问题的。当给 SVG 字体定义 text-overflow: ellipsis 的时候,所有的字符都莫名其妙的不见了,只剩下省略号。比如”My text…”最终显示成了”…”。</p>
<p>性能</p>
<p>说到性能,我通常会提到用户体验,以及更重要的关系户感官体验的性能(user-perceived performance)。Matt 和 Adam 在各自专题中都有提到事关@font-face的性能问题,Matt指出iOS中的文本样式短失效(FOUT)问题实际上是“无文本闪烁”,他发现尽管网页渲染完毕,使用网页字体的文本内容也会因为字体文件没有下载完成而显示为空,他进一步指出,字体的下载只有在使用网页字体的dom元素被渲染的时候才会开始。这里我们采用了一种hack的手法来将字体下载时机提前——将字体定义放在<html>标签上,当然,更好的方式还有待进一步研究发掘。</p>
<p>网页字体的另一个性能问题是字体文件的大小,在美国我们可以肆无忌惮的使用网页字体,因为字体无非由26个英文字母和一些标点符号组成而已,Adam 提到在亚洲文字的字体文件则要庞大的多,有的甚至能达到4~5MB。因此,如果你想在亚洲网站中应用非标准的字体,你需要重新审视由此造成的性能问题。</p>
<p>小结</p>
<p>看起来我们还有很长的路要走,还需要更深入的研究在网速允许的情况下@font-face的应用,除了兼容性和性能问题之外,还有很多难题需要攻克,非常感谢 Matt 和Adam 的分享,让我们更好的理解围绕网页字体的页面设计原理。</p>
QCon 2011 后记
2011-04-17T00:00:00+08:00
urn:uuid:b9a827a7-cff0-46ea-8f34-ef665fee15b5
<p>关于Qcon 2011</p>
<p>之前年初我参加了新版淘宝首页的开发,做了一些html5的实践,正好这次QCon有学鹍主持的html5专题,小马就推荐我去QCon分享一下这方面的心得,所以对我来说,能参加这次QCon很幸运,也很忐忑。一方面,我在html5方面的确算不得专家,另一方面,淘宝在html5实践之路上也在摸着石头过河,不过,感谢学鹍的鼓励,还有澄净、承玉、圆心和完颜的帮助,让我仔细梳理html5实践原则和一些教训,这才有了这个ppt</p>
<iframe src='http://www.slideshare.net/slideshow/embed_code/7576035' width='500' height='410' border=0></iframe>
<p>说起来,这是我第二次参加QCon,之前QCon关于纯粹Web前端的专题很少,就像小马说的,QCon大会是后端开发工程师和架构师的技术大会,不过这次QCon前端的专题一下子增加到了三个,有点小意外。此外,敏捷开发、Java的回归、关于测试和服务器集群优化的专题演讲依然让人收获颇丰。</p>
<p>关于敏捷</p>
<p>这次QCon“敏捷开发”突然就火了起来,当然不是说之前没有“敏捷”,甚至我们每天都在“敏捷”之中。那么,对于前端工程师来讲,有无必要去关注“敏捷”呢?我认为不但要关注,而且要有意识历练自己成为敏捷教练,也就是说前端工程师做不了PM(项目经理)的职位,不代表不能具备PM的能力,如果由前端工程师来驱动项目(比如Kissy的开发和淘宝首页的开发),能不能做到真正的敏捷高效,如何合理的做需求排期、安排迭代开发?这种基本能力应当是每个工程师——当然包括前端工程师——所必备的技能,我想,这也是前端工程师自身发展的一个必由节点。</p>
<p>关于Java</p>
<p>我在QCon上听到关于前端工程师的言论最多的就是,“怎么看,都感觉前端写的代码比不上后端工程师那么专业功底扎实,写出来的东西也没有后端稳重可靠”。尽管这种言论有失偏颇,但也说明了IT行业对前端开发的普遍看法,没错,前端工程师多是半路出家,毕竟入门前端开发实在太简单了,所以我们在招聘前端工程师的时候都会加上一条:至少熟悉一门后端语言(当然熟悉Java更好,淘宝的后台大部分使用Java),如果前端工程师仅仅将关注点放在html/css/js上面,其成长将迅速到达瓶颈,所以,和传统后台开发语言不同,前端的学习曲线是先缓后陡,越到后来越会发现数据结构、设计模式、编译原理、网络协议的重要性,而这些内容,正是传统后端工程师所擅长的。这里不是说前后端之间不容水火,而是掌握全面的知识结构,对于前端工程师的成长百利而无一害。因此,当今天大家重新将目光聚焦在Java身上,重新审视Java时候,对于前端工程师,也要将目光收回,从箱底翻出那些破旧的计算机专业课本,这些东东才是我们更上一层楼的关键所在。</p>
<p>关于测试</p>
<p>测试的话题一直都备受关注,这次QCon就有诸多专家做了这方面的分享,而我更想了解如何做前端测试,遗憾的是,专家的分享依然侧重于测试平台建设和分层测试理论。不过,不管是平台自动化还是分层理论,大家至少有两个共识,第一,对于MVC来讲,对M做测试最容易,对C做测试难度次之,对V做测试最难;第二,代码质量直接影响到测试效率。而需求变化频繁又影响代码质量,似乎注定测试是一个永恒的难题。不过,对于前端来讲,可以先让M可测,再深入搞定C,最后集中精力攻克V的测试难题,当然在这之前,则要先教会小白们如何写出符合MVC的代码。</p>
<p>关于前端开发</p>
<p>这次QCon上三个前端专题基本描述清楚了前端开发的三个发展方向,第一,面向服务器端的JavaScirpt,第二、手持终端,第三、传统前端从html4到html5的进化。我想这种分工是一种必然,当然不是说现在一定是做分工的最佳时机,而是作为前端工程师来讲,应当具有这种危机意识和一定的前瞻性,而不管哪个方向,我们都能看到这个职位对前端工程师专业素养极高的要求。</p>
<p>其实,这次QCon给我带来的思考不止这些,我也非常高兴能把这些体会分享给大家,当然这次QCon上和html5专题的几位讲师(谢子斌、hax、杜欢)的合作相当愉快,学鹍对这个专题也是信心满满,也非常期待和他们的再次合作:</p>
<p><img src="http://ued.taobao.com/blog/wp-content/uploads/2011/04/qcon_html5.jpg" alt="qcon" /></p>
[翻译]YUI3.4.0 中对 Seed 和 Loader 的改造
2011-03-11T00:00:00+08:00
urn:uuid:cc706484-0a98-4403-bb96-6fca169c37c9
<ul>
<li>原文:http://www.yuiblog.com/blog/2011/07/01/yui-and-loader-changes-for-3-4-0/</li>
<li>标题:YUI and Loader changes for 3.4.0</li>
<li>作者:Dav Glass</li>
<li>译文:YUI3.4.0 中对 Seed 和 Loader 的改造</li>
</ul>
<p>在 YUI3.4.0 中,我们开始对 Loader 的核心逻辑进行升级改造。Loader 的性能有了很大提升,而且更加健壮,可以在更多场景下非常方便的使用(比如在服务器环境中)。同时我们会给出YUI的发展路线图,但首先还是有必要解释一下本次更新带来了哪些新内容,为什么做这些更新,以及这些更新对开发者带来的影响。对于大多数用例来说,开发者甚至不会察觉到有什么变化,但有一点变化最明显,就是速度更快,而且加载的资源文件更小了。</p>
<p>种子文件</p>
<p>我们首先来看 YUI 种子文件的一些变化,在之前的版本中,YUI 种子文件非常小,不包含 Loader 以及它的元组件(meta-data)。我们发现在90%的用例中,种子文件并未像我们设计的那样工作。大部分人引用种子文件之后再去载入他们自有的模块,也就意味着种子文件需要先获取 Loader,再计算模块依赖关系,然后再载入模块。我们感到这种策略是一种错误,它会带来一次额外的 http 请求,因此在新版的 YUI 中我们将 Loader 和它的元组件都整合进种子文件中。当然,这会让种子文件体积变大一些,但由于元组件已经包含在种子之内,页面模块的加载自然会提速很多。</p>
<p>如果你仍希望使用旧的方式加载YUI,你只需引入 yui-base 种子文件就可以了。基于 yui-base 可以单机模式运行YUI,它也可以根据需要去自动加载 Loader。如果你想更细粒度的使用 YUI,我们提供了 yui-core 种子文件,yui-core 文件几乎就是原来的 yui-base。</p>
<pre><code>/build/yui/yui-min.js //YUI Seed + Loader
/build/yui-base/yui-base-min.js //Old YUI Seed with Loader fetch support
/build/yui-core/yui-core-min.js //Old yui-base without Loader fetch support
</code></pre>
<p>注意,这些URL和之前的URL有所不同。如果想使用 yui/yui-base.js 文件,则需要重新定位至 yui-core/yui-core.js,如果你想使用旧的方式来加载种子和 Loader,则需要使用 yui-base/yui-base.js 种子文件。</p>
<p>促使我们对 YUI 作这种调整的另一个重要原因是,根据 YUI 的发展路线图,我们需要 YUI 将来运行于各种平台上。如果你有 combo 服务器(译注:combo 是合并的意思,这里指可以在服务器端合并脚本的服务器),则旧有的种子外加 Loader 的使用方式是ok的,我们可以将种子和 Loader 合并入一个 http 请求。那么 YUI 如何运行在服务器端、离线应用程序以及手持终端里呢?这些场景所需的种子文件需要做到最小化,同时又要保持各自所需的功能。</p>
<p>模块依赖计算器(Rullups)</p>
<p>(译注:YUI 提供了两种模块粒度,粗粒度和细粒度,分别面向初级开发者和高级开发者使用。比如 event 中就包含了 event-key 和 event-move 等子模块,这里所说的“模块依赖计算”不是“向下”计算而是“向上”计算,比如我引用了 event-key,计算器得知它属于 event 大模块,这时就会加载 event,而放弃加载 event-key,由于 event 是很多小模块合写在一起的,因此可能会载入不需要的功能)</p>
<p>接下来,我们将模块依赖计算器从 core 中删除掉了,同时将 Loader 中的 allowRollup 属性默认值设为 false。这意味着什么?希望它不会带来任何影响!在解释这个更新造成的影响之前,我们首先解释下背后的原因。还是“性能”——模块加载的负担过重。来看这个例子:</p>
<pre><code>Module A: requires event-a, event-b
Module B: requires event-c, event-d
</code></pre>
<p>在 YUI3.4.0 之前版本中的“模块依赖计算器”是用来决定还需加载哪些子模块,当同时加载这两个模块时,比如这个例子中通过计算得知需要加载 event 模块,这个模块包含:</p>
<pre><code>event.a, event.b, event.c, event.d, event.e, event.f, event.g, event.h
</code></pre>
<p>其实所载入的这些模块有些并不是我们真正需要的。如果关掉“模块依赖计算器”,YUI 将只会请求实际引用的模块,而不会去请求更多。多数情况下你不会注意到这些,如果你是模块的开发者,则可能会遇到一些麻烦,之前运行好好的模块现在不能运行了,其实是之前他们只是“碰巧”可以运行而已。来看一个实际的例子,Dial:</p>
<p>在3.3.0中,Dial引用了这些:</p>
<pre><code>requires: [
'widget',
'dd-drag',
'substitute',
'event-mouseenter',
'transition',
'intl'
]
</code></pre>
<p>对于大多数场景来说,Dial 在 3.4.0 下可以照常工作,但不支持键盘事件。在简单分析之后发现,“模块依赖计算器”实际上请求了整个 Event 模块(包括event-move和event-key)。YUI3.4.0 中关掉了“模块依赖计算器”,Dial 也不再去请求 event-move 子模块所属的母模块 event。为了让 Dial 的模块引用更加细致有针对性,则需要引用所有实际用到的小模块,这样代码才会正常工作:</p>
<pre><code>requires: [
'widget',
'dd-drag',
'substitute',
'event-mouseenter',
'event-move',
'event-key',
'transition',
'intl'
]
</code></pre>
<p>对于模块开发者来说,清楚的知道自己的组件所依赖哪些模块非常重要,这也是比较好的习惯和实践。不要想当然去引用“上游模块”(就是刚才提到的粗粒度模块),始终确保只引用了真正需要的模块。</p>
<p>这也意味着模块引用的定义更加合理,比如,datatype-date 内置支持全球化格式的数据,在之前的版本中这样使用:</p>
<pre><code>Y.Intl.getAvailableLangs('datatype-date');
</code></pre>
<p>但这个模块并不真正包含某种语言(datatype-date-format 模块包含)。因此需要指定正确的模块引用:</p>
<pre><code>Y.Intl.getAvailableLangs('datatype-date-format');
</code></pre>
<p>编译规则的修改和删除子模块</p>
<p>除此之外,接下来的更新是修改了编译后的文件目录并从core中删除子模块。其实子模块并没有真正删除,只是元模块数据结构改变了。它使得当前 YUI 可以向后兼容。</p>
<p>core 中的子模块有很多问题,我们必须把他们一一解决掉。第一个是性能。每次计算依赖关系的时候,程序会把子模块/插件结构中的每个节点都遍历一遍。在 Loader 运行过程中大量的遍历操作会严重损耗性能。去掉了 core 中的子模块支持,可以免去大量低效的函数调用和迭代运算。</p>
<p>我们对 Loader 做了修改,以便能通过模块的元数据中属性来定义需要引用的模块,这样便可以载入我们指定的模块而不是去查找原始模块。如果你引用了“dd”(拖拽),Loader 将会把“dd”拆分成元模块(子模块),属性值看起来就像这样:</p>
<pre><code>"dd-ddm-base,dd-ddm,dd-ddm-drop,
dd-drag,dd-proxy,dd-constrain,
dd-drop,dd-scroll,dd-drop-plugin"
</code></pre>
<p>在 YUI 种子文件当中同样包含了“垂直模块依赖计算”或者称之为“别名”。模块的定义和 Loader 中的元模块是一模一样的。这样的话就可以直接根据“模块依赖配置工具”(Dependency Configurator)来获得文件的引用地址,同样也可以使用剥离出 Loader 的“模块依赖计算器”,在未来的版本发布中,我们还会对这部分功能作进一步的提炼。</p>
<p>介绍过这些更新之后,我们来看一下 YUI 的项目文件,在之前的版本中,子模块决定模块的文件路径,比如:</p>
<pre><code>"dd": {
"submodules": {
"dd-drag":
// Module data
}
}
</code></pre>
<p>在3.3.0中编译“dd”得到的文件结果是:</p>
<pre><code>/build/dd/dd-drag.js
/build/dd/dd-ddm.js
/build/dd/dd-drop.js
</code></pre>
<p>在3.4.0的新编译规则下,“dd”编译后的结果是:</p>
<pre><code>/build/dd-drag/dd-drag.js
/build/dd-ddm/dd-ddm.js
/build/dd-drop/dd-drop.js
</code></pre>
<p>这样我们就可以将模块元数据中的“path”属性删掉了,减少了文件体积,也免去了根据模块名称查找它的文件路径的工作。</p>
<p>如果你之前引用了配置好的合并了文件的(combo)URL,那么升级 YUI 到 3.4.0 后则需要重新生成这个 URL。</p>
<p>本次更新也有不足,如果你引用了合并了多个模块文件的 URL 用以对页面进行初始化,则不能只更新版本号,你需要重新到模块依赖配置工具中获得新的 URL。</p>
<p>未来</p>
<p>我们还会对YUI作进一步的提炼、重构、优化,并将 Loader 和种子文件中的各个功能点的代码体积降到最低。当然首要工作依然是将 YUI 移植到除了客户端浏览器平台之外的服务器端、命令行和手持终端的各个平台中。</p>
JavaScript语法检查插件 jsLint for Vim
2011-01-04T00:00:00+08:00
urn:uuid:7fb56684-2ad6-4932-a87a-a3005117b46f
<p>工欲善其事,必先利其器。作为更专业的前端工程师,我们需要强劲的IDE协助我们写出规范、美观、漂亮的JavaScript代码,首先要作的就是对代码进行合法性检查,而通过 <a href="www.jslint.com" target="_blank">www.jslint.com</a> 进行手工操作又显得碍手碍脚。为了提高效率,这里推荐使用 <a href="http://www.vim.org/scripts/script.php?script_id=2729" target="_blank">jsLint + Vim(gVim)</a>,能够协助你达到事半功倍的效果。</p>
<p>首先,和 <a href="http://www.javascriptlint.com/" target="_blank">JavaScriptLint</a> 不同<strong>[注1]</strong>,<a href="http://www.vim.org/scripts/script.php?script_id=2729" target="_blank">jsLint</a> 是需要 <a href="http://en.wikipedia.org/wiki/JavaScript_engine" target="_blank">JavaScript 引擎</a>的支持的,linux中可选的有基于 C 语言的 <a href="http://en.wikipedia.org/wiki/SpiderMonkey_%28JavaScript_engine%29" target="_blank">Spidermonkey</a> 和基于 Java 的 <a href="http://en.wikipedia.org/wiki/Rhino_%28JavaScript_engine%29" target="_blank">Rhino</a>,考虑到速度,推荐使用 Spidermonkey。另外,<a href="https://github.com/hallettj/jslint.vim/blob/master/ftplugin/javascript/jslint.vim" target="_blank">jsLint.vim</a> 初始配置挂载的监听有些冗余,这会导致 <a href="http://www.vim.org" target="_blank">Vim</a> 运行很慢,影响编码的效率,这里我 hack 了一份 <a href="https://github.com/jayli/jayli.github.com/blob/master/gallery/vim/jslint.vim" target="_blank">jslint.vim</a>,只用F4键就可以开启/关闭语法检查,下面介绍配置方法(linux & windows)。</p>
<p><strong>jsLint + vim for Linux</strong></p>
<p><a href="http://ued.taobao.com/blog/wp-content/uploads/2010/11/linux界面.png"><img class="alignnone size-full wp-image-2754" src="http://ued.taobao.com/blog/wp-content/uploads/2010/11/linux界面.png" alt="" width="525" height="317" /></a></p>
<p>1,准备JS引擎</p>
<p>linux 下默认没有 <a href="http://en.wikipedia.org/wiki/JavaScript_engine" target="_blank"> JavaScript 引擎</a>,需要安装,旧版本的 ubuntu 通过apt-get来安装</p>
<pre><code>sudo apt-get install spidermonkey-bin
</code></pre>
<p>新版的 ubuntu 需要通过下面这个包安装</p>
<p><a href="https://launchpad.net/ubuntu/hardy/i386/spidermonkey-bin/1.8.1.4-2ubuntu5" target="_blank">https://launchpad.net/ubuntu/hardy/i386/spidermonkey-bin/1.8.1.4-2ubuntu5</a></p>
<p>其他linux发行版可以通过源码安装:</p>
<p><a href="ftp://ftp.mozilla.org/pub/mozilla.org/js/" target="_blank">ftp://ftp.mozilla.org/pub/mozilla.org/js/</a></p>
<p>2,安装ruby环境</p>
<p>ubuntu下安装:</p>
<pre><code>sudo apt-get install ruby
</code></pre>
<p>redhet系发行版中的安装:</p>
<pre><code>yum install ruby
</code></pre>
<p>3,安装vim,通常linux中自带,不用安装</p>
<p>4,下载<a href="http://www.vim.org/scripts/script.php?script_id=2729" target="_blank"> jsLint 插件</a>,下载后解压缩,把其中的 javascript 目录拷贝至 $VIM/plugin/中(作者给的文档有误,不应是$VIM/ftplugin/),当然也可以放到 ~/.vim/plugin/ 中</p>
<p>5,将解压后 jslint/bin 目录中的 jslint 文件拷贝至 /usr/bin 中,也可以拷贝到~/bin/中</p>
<p>6,下载 <a href="http://jayli.github.com/gallery/vim/jslint.vim" target="_blank">http://jayli.github.com/gallery/vim/jslint.vim</a> 文件,覆盖 $VIM/plugin/javascript/jslint.vim</p>
<p>7,完成,打开一个js文件,用F4唤醒语法检查,再按F4关闭语法检查</p>
<p><strong>jslint + gvim for windows</strong></p>
<p><a href="http://ued.taobao.com/blog/wp-content/uploads/2010/11/windows界面.png"><img class="alignnone size-full wp-image-2756" src="http://ued.taobao.com/blog/wp-content/uploads/2010/11/windows界面.png" alt="" width="487" height="357" /></a></p>
<p>windows 下自带 <a href="http://en.wikipedia.org/wiki/CScript" target="_blank">CScript</a>,不用再安装其他 JavaScript 引擎</p>
<p>1,安装<a href="http://rubyinstaller.org/" target="_blank">ruby运行环境</a></p>
<p>2,安装 <a href="http://www.google.com.hk/search?hl=zh-CN&safe=strict&biw=1680&bih=868&q=gvim&aq=f&aqi=&aql=&oq=&gs_rfai=" target="_blank">gvim</a>,假设安装到 C:/Program Files/Vim 中</p>
<p>3,下载<a href="http://www.vim.org/scripts/script.php?script_id=2729" target="_blank"> jsLint 插件</a>,下载后解压缩,将 ftplugin 目录中的 javascript 文件夹复制到 C:/Program Files/vim/vim72/plugin/ 目录中</p>
<p>4,将 jslint 解压缩后的“/bin/jslint”文件添加后缀名 “exe”,并将其所在的路径添加到环境变量的 Path 中,比如我将 jslint.exe 放到 C:/user/bachi/ 中,配置环境变量</p>
<p><a href="http://ued.taobao.com/blog/wp-content/uploads/2010/11/环境变量配置.png"><img class="alignnone size-full wp-image-2757" src="http://ued.taobao.com/blog/wp-content/uploads/2010/11/环境变量配置.png" alt="" width="373" height="297" /></a></p>
<p>5,下载 <a href="http://jayli.github.com/gallery/vim/jslint.vim" target="_blank">http://jayli.github.com/gallery/vim/jslint.vim</a> 文件,覆盖 C:/Program Files/vim/vim72/plugin/javascript/jslint.vim</p>
<p>6,修改这个 <a href="https://github.com/jayli/jayli.github.com/blob/master/gallery/vim/jslint.vim" target="_blank">jslint.vim</a> 文件,将 vim 安装路径替换为绝对路径,找到</p>
<pre>expand("~/vimfiles/ftplugin/javascript")</pre>
<p>修改为</p>
<pre>expand("C:/Program Files/Vim/vim72/plugin/javascript")</pre>
<p><a href="http://ued.taobao.com/blog/wp-content/uploads/2010/11/修改文件.png"><img class="alignnone size-full wp-image-2758" src="http://ued.taobao.com/blog/wp-content/uploads/2010/11/修改文件.png" alt="" width="581" height="54" /></a></p>
<p>7,完成,打开一个 js 文件,用F4唤醒语法检查,再按F4关闭语法检查</p>
<p>ps:其实很早之前,<a href="http://www.gracecode.com/" target="_blank">明城</a>就介绍过使用 <a href="http://www.gracecode.com/archives/2902/" target="_blank">JavaScriptLint + Vim进行语法检查</a><strong>[注2]</strong>,这种方法也相当不错,但使用体验稍有缺憾,语法提示单独占用视窗,看起来更像专门的 Debug 操作,而我更希望在编码过程中,实时监控我刚写过的代码的正确性,而给出语法提示也不应当进入一个“Debug”过程,只要编辑过程中,我用眼睛余光能注意到光标所在行的错误提示就可以了,没必要打开一个视窗给我看我有多少bug,另外,JavaScriptLint 的语法检查非常苛刻,我希望能有更加实用更加宽松的语法检查。很碰巧,jsLint 可以满足我这种挑剔的需求</p>
<ul>
<li><strong>[注1]</strong>:<a href="http://www.javascriptlint.com" target="_blank">JavaScriptLint</a> 的语法检查相比<a href="http://www.jslint.com/lint.html" target="_blank">老道的 jsLint</a> 更为苛刻,大量鸡肋警告非常干扰视线,比如 <a href="http://code.jquery.com/jquery-1.4.2.js" target="_blank">jquery-1.4.2.js</a> 通过 JavaScriptLint 检查有164个警告,通过 jsLint 检查只有10个警告,正是因为此,JavaScriptLint 实际上增加了我们编码的负担。</li>
<li><strong>[注2]</strong>:明城的文章中有小小的误导,JavaScriptLint 和 jsLint 是两个不同的东东,这里推荐的是老道的 jsLint,而不是JavaScriptLint。</li>
</ul>
淘宝2011新版首页开发实践
2011-01-01T00:00:00+08:00
urn:uuid:d5ea4ee2-7adf-4354-b697-3f60201f1b0f
<p>本文同期发表于 <a href="http://ued.taobao.com">http://ued.taobao.com</a></p>
<iframe border=0 src='http://www.slideshare.net/slideshow/embed_code/6516501' width='500' height='410'></iframe>
<p>新年钟声刚过,<a href="http://www.taobao.com" target="_blank">淘宝新版首页</a>全“心”上线了,这次设计大胆的将布局从 960px 伸展至 1000px,页面更通透,新首页更大范围的实践了<a href="http://en.wikipedia.org/wiki/HTML5"> HTML5</a> 和<a href="http://www.w3.org/TR/css3-roadmap/"> CSS3</a>,全面兼容 iPad,并在<a href="http://www.w3.org/WAI/intro/accessibility">可访问性</a>方面有了更多积极的尝试。对于我来讲,这次开发着实是一次奇妙的经历,也让我对可访问性、html5 和性能优化有了新的认识。</p>
<p>其实 <a href="http://en.wikipedia.org/wiki/HTML5">html5</a> 并不是那么遥不可及,现在也有着不少针对 pc 终端的 <a href="http://www.impressivewebs.com/demo-files/easy-html5-template/">html5 template</a>,如果不甚考虑 ie6/7/8 禁用脚本的情况,完全可以放手运用 html5 标签。那么针对那些 ie6/7/8 禁用脚本的用户,我们参照了 <a href="http://www.facebook.com">facebook</a> 的做法,即引导用户进入带有noscript标识的 <strong>“/?_fb_noscript=1”</strong>页面,用 html4 标签替换 html5 标签,这要比为了保持兼容性而写大量 hack 的做法更轻便一些。</p>
<p>如果你足够细心,就会发现新首页并未完全遵循“<a href="http://www.w3.org/TR/css3-grid/">栅格</a>”,因为一个很纯粹的文档中,实现栅格效果所使用的层层 wrap 本身就缺乏语义,html5 带来了更多语义化的标签,这和缺乏语义的栅格实现是如此格格不入,摆脱栅格,容器用绝对定位,不用写那么多 hack,岂不多快好省~</p>
<p>另外,关于性能优化,之前我们的确过于依赖 <a href="http://developer.yahoo.com/yslow/">yslow</a>、<a href="http://code.google.com/intl/zh-CN/speed/page-speed/">pagespeed</a> 的评分,其实,这些条条框框才是真正阻碍我们作 <a href="http://www.stevesouders.com/blog/2010/05/07/wpo-web-performance-optimization/">WPO</a> 的拦路虎,不是说这些指标不科学,而是他们限制住了我们的思维和视野,更何况,他们都缺少对“加载/渲染时间”这个最重要的因素的评估,当用户更快的看到并可用页面(尤其是首屏),才是真正的性能提升,因此,这次开发特意针对 First Rendering(首次渲染)的指标进行一些重构,重写了几乎所有的逻辑层 js 代码 (domready 之前,甚至 Render 出 UI 之前,js 已经在运行了),当 js 效率更高,CPU 损耗更少时,浏览器才会更多的将硬件资源投入到渲染 Dom 本身,First Rendering 自然会更加提前,后续的渲染也会提速。可以参照新旧淘宝首页的 CPU 耗能对比,以及其对 First Rendering(绿线)的影响。</p>
<p>2010(旧)首页加载 CPU 损耗</p>
<p><img class="alignnone size-full wp-image-3441" src="http://ued.taobao.com/blog/wp-content/uploads/2011/01/ued-blog-wpo-1.png" alt="" width="600" height="101" /></p>
<p>2011(新)首页加载 CPU 损耗:</p>
<p><img class="alignnone size-full wp-image-3442" src="http://ued.taobao.com/blog/wp-content/uploads/2011/01/ued-blog-wpo-2.png" alt="" width="600" height="101" /></p>
<p>当然,延迟加载、延迟渲染等技术在这里依然适用,上次淘宝首页改版<a href="http://www.chencheng.org/blog/2010/01/06/dev-share-for-taobao-new-homepage/">云谦同学作了详尽的总结</a>,这里就不再赘述了。更多内容大家可以到这里<a href="http://www.slideshare.net/lijing00333/2011-6516501">下载 ppt</a>。</p>
<p>此致,鸣谢<a href="http://www.pushiming.com/blog/">法海</a>、<a href="http://yiminghe.javaeye.com/blog/">承玉</a>、<a href="http://www.songwa.org/">王松</a>、玉澧、<a href="http://besteric.com/">黑三</a>,最后要特别感谢下玉澧童鞋,有了你的妙笔,这次首页才会如此闪亮。</p>
将你的 KISSY 程序移植到服务器端 – nodejs-kissy 项目简介
2010-12-19T00:00:00+08:00
urn:uuid:73850b0d-7217-475b-b665-1034ca71b2dd
<p>如果你还不了解 NodeJS,请参照 <a href="http://nodejs.org/" target="_blank">NodeJS.org</a>,简言之:</p>
<blockquote>Node.js 是服务器端的 JavaScript 运行环境,它具有<a href="http://en.wikipedia.org/wiki/Non-blocking_algorithm" target="_blank">无阻塞</a>(non-blocking)和<a href="http://en.wikipedia.org/wiki/Event-driven_programming" target="_blank">事件驱动</a>(event-driven)等的特色,Node.js 采用 <a href="http://code.google.com/p/v8/" target="_blank">V8</a> 引擎,同样,Node.js 实现了类似 <a href="http://apache.org/" target="_blank">Apache</a> 和 <a href="http://nginx.org/" target="_blank">nginx</a> 的web服务,让你可以通过它来搭建基于 JavaScript 的 Web App。</blockquote>
<p>你可以通过我们前些天 team 内的一个分享来了解下 NodeJS</p>
<iframe src='http://www.slideshare.net/slideshow/embed_code/5576953' width='500' height='410' border=0></iframe>
<p><strong>nodejs-kissy 项目</strong></p>
<p><a href="http://github.com/kissyteam/kissy" target="_blank">KISSY</a> 是淘宝网开发的一款轻巧灵活的JS框架,如今已经是1.1.5版本,并在淘宝网广泛应用,在浏览器端给我们带来更加清新的体验,今天让我们更进一步,我们发起了<a href="http://github.com/kissyteam/nodejs-kissy" target="_blank">nodejs-kissy</a> 项目,你的 KISSY 程序可以无缝移植到服务器端了</p>
<p><a href="http://ued.taobao.com/blog/wp-content/uploads/2010/11/nodejs-sombrero.png"></a><a href="http://ued.taobao.com/blog/wp-content/uploads/2010/11/未标题-1.png"><img class="alignnone size-full wp-image-2689" src="http://ued.taobao.com/blog/wp-content/uploads/2010/11/未标题-1.png" alt="" width="323" height="86" /></a></p>
<p><strong>从这里开始 nodejs-kissy</strong></p>
<p>得益于 KISSY 轻巧的设计,核心模块可以很充分的解偶,所以对 KISSY 作简单hack就能够运行在 NodeJS 上。但开始之前应该首先准备好预装了 <a href="http://npmjs.org/" target="_blank">npm</a> 的服务器(linux/FreeBSD/MacOS/cygwin),npm 是 NodeJS 软件包管理器,类似yum 和 apt-get,通过他来安装 NodeJS 的软件包会非常方便。</p>
<p>准备 npm:</p>
<pre><code>curl http://npmjs.org/install.sh | sh
</code></pre>
<p>如果你的账户没有权限则先准备好目录权限:</p>
<pre><code>sudo chown -R $USER /usr/local
</code></pre>
<p>安装成功后就可以通过 <code>"npm install package_name"</code> 命令来安装 NodeJS 软件包了</p>
<p>安装 Nodejs-KISSY 的依赖:服务器端没有浏览器环境,要运行js需要模拟真实的浏览器环境,因此 KISSY 需要依赖一些包:</p>
<pre><code>npm install jsdom
npm install htmlparser
npm install express
npm install connect
</code></pre>
<p>安装Nodejs-kissy:</p>
<pre><code>npm install kissy
</code></pre>
<p>运行 “hello world”:</p>
<p>新建文件 helloworld.js</p>
<pre><code>var S = require('kissy').KISSY;
S.ready(function(S){
S.log('hello world!');
});
</code></pre>
<p>运行:</p>
<pre><code>node helloworld.js
</code></pre>
<p><strong>更方便的移植?</strong></p>
<p>你可能会好奇,服务器端没有浏览器,为什么KISSY能如此轻松的运行在服务器端?这主要是因为KISSY的模块加载机制是脱离浏览器环境的,也就是说KISSY.use、KISSY.add、KISSY.app是和环境无关的,它只关系到你组织代码的方式和风格,另外,得益于足够原生态的KISSY-DOM实现,KISSY只调用到domjs(domjs的高层api是面向YUI3设计的)的基础方法,所以DOM相关操作依然可以无缝嫁接到服务器端,相对于YUI3核心模块的深层次耦合,KISSY的移植实在是太轻松了。</p>
<p><strong>策略上的取舍</strong></p>
<p>KISSY 基于“one for all”理念的core和粗粒度的widget,使得KISSY可以使用更少的"引入文件"来执行程序,而非必要一定采用combo(即使采用combo性能未必提高多少),这样使得require的逻辑策略更简便。</p>
<p><strong>所见即所得</strong></p>
<p>和YUI3一样,KISSY-Loader 也可以非常方便的引入外部脚本,不管脚本是存放在服务器上,还是通过http请求到,开发者只要require fullpath即可,非常低碳,比如我可以这样运行:</p>
<pre><code>var S = require('kissy').KISSY;
S.add({
'menu':{
fullpath:'http://cdn/menu.js'
}
}).use('menu',function(S){
new S.Menu('ID');
});
</code></pre>
<p>总之,你在浏览器端怎么用 KISSY,你就在服务器端怎么写,接下来,nodejs-kissy 项目的主要工作是更多的测试和提高其健壮性。nodejs-kissy 和 KISSY 一样基于 <a href="http://github.com/kissyteam/kissy/blob/master/LICENSE.md" target="_blank">MIT</a> 协议,你可以通过 <a href="https://github.com/kissyteam/nodejs-kissy" target="_blank">fork github</a> 上的项目来参与 nodejs-kissy 的开发。</p>