TBAD F2E 2010 review

3,451 views

Published on

淘宝广告前端2010review

1 Comment
22 Likes
Statistics
Notes
No Downloads
Views
Total views
3,451
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
134
Comments
1
Likes
22
Embeds 0
No embeds

No notes for slide

TBAD F2E 2010 review

  1. 1. TBAD F2E 2010 & Velocity China & D2 Review <br />淘宝广告事业部 李牧<br />2010-12-20<br />
  2. 2. overview<br />JavaScript Ninja 出品的代码和启示<br />Facebook QuicklingPageCache Vs. Ajaxxx<br />There and Back Again : HTC(HTML Component)<br />Facebook BigPipe++ : Streaming Anywhere<br />客户端无阻滞:第三方广告代码的实践<br />服务端无阻滞:CommonJSNodeJSCFO体系Web死后jser的未来<br />JavaScript包管理+模块化 : YUI3 & Kissy Vs. KissyLite<br />Google Clousure Compiler 启示 : KissyLite预编译时间窗口优化性能<br />Jscex 和kslite对异步编码的简化<br />
  3. 3. JavaScript Ninja 出品的代码和启示<br />Topic 1:<br />
  4. 4. DomReady<br />Firefox Chrome Safari Opera:<br />DOMContentLoaded<br />IE:<br />doScrollor script defer<br />onreadystatechangefor iframe<br />
  5. 5. <script> onload<br />Dom载入的JS文件载入完成且执行完成的事件<br />IE Opera:<br />onreadyStateChange<br />Firefox Chrome Safari Opera:<br />onload<br />
  6. 6. insertAdjacentHTML<br />IE Chrome Safari Opera:<br />insertAdjacentHTML<br />Firefox:<br />HTMLElement.prototype.insertAdjacentElement= function(where, parsedNode) { };<br />HTMLElement.prototype.insertAdjacentHTML= function(where, htmlStr) { };<br />
  7. 7. iframedJS<br />父页面升级document.domain,IE下IframedJS解决方案:<br /><iframe id= src= "javascript:void(( function(){var d=document;d.open(); d.domain='a.com';d.write('');d.close()})())" ></iframe><br />BugFix@CKEditor<br />
  8. 8. DOMNodeInserted<br />Firefox Chrome Safari Opera:<br />DOMNodeInserted<br />IE6,7:<br />CSS Expression <br />IE8std: <br /> Override : innerHTML,appendChild…<br />屈超:Bookmarklet型(云端)应用的前端架构@D2<br />
  9. 9. Tag Customed<br />Firefox Chrome Safari Opera IE9:<br />直接使用<br />IE6,7,8:<br />document.createElement("tagName")<br />屈超:Bookmarklet型(云端)应用的前端架构@D2<br />
  10. 10. Range : insertNode<br />Firefox Chrome Safari Opera:<br />insertNode<br />IE:<br />圆心的实现<br />http://www.planabc.net/2010/11/26/range_insertnode/<br />
  11. 11. Ninja 的代码和启示<br />不同浏览器,使用不同途径实现相同功能.<br />对JavaScript或Dom的功能进行补强.<br />解决实际开发中遇到的重大困扰!<br /> --了解更多的浏览器特性,包括那些某种浏览器独特的特性以拓展解决问题思路,因为特性都是为解决实际问题而加入的.<br />
  12. 12. Facebook QuicklingPageCacheVs. Ajaxxx<br />Topic 2:<br />
  13. 13. 网站性能优化的目的<br />运行流畅加载迅速<br />
  14. 14. Ajaxxx<br />架构来自于系统特点.<br />1.页面不多,<100个<br />2.多数页面重复,由组件搭建<br />3.页面有数据的区块不多<br />4.不需要SEO<br />
  15. 15. Ajaxxx<br />加载迅速<br />1.所有静态资源在CDN上<br />2.通过Ajax只加载需要的数据<br />3.没有任何静态资源加载2次以上<br />展现流畅<br />1.没有load,unload消耗<br />2.没有重复渲染<br />3.基于事件绑定的组件框架<br />
  16. 16. 同类的 Facebook Quickling<br />
  17. 17. QuicklingvsAjaxxx<br />Link Controller – FB使用事件代理,我们使用的是原生的link<br />HistoryManager -- 基本一致<br />Bootloader -- 我们有面向开发环境的优化<br />Busy Indicator<br />CSS Unloading<br />Resetting timer functions<br />Permanent link<br />
  18. 18. 内存问题<br />Facebook 会在10个页面之后强制刷新<br />我们不能这样做,因为IE6强制刷新丢失存在于iframe的历史<br />我们解决问题的两个方向<br />1.将历史存入cookie或其他本地存储模式,强制刷新能够恢复历史,配合页面间内存泄露预防<br /> 2.减少YUI3依赖,解决页面内内存泄露问题<br />
  19. 19. PageCache<br />
  20. 20. PageCache启示<br />我们动态数据及时性要求高,动态数据少,所以不缓存动态数据.<br />Facebook缓存动态数据遇到的非常棘手问题我们都没有.<br />Incremental updates<br />In-page writes<br /> Cross-page writes<br />如果我们系统预知到了这些问题,我们不会这样架构.<br />但从Facebook,我们看到的是解决问题的智慧,勇气和信心!<br />
  21. 21. 同类的 New Twitter<br />MUSTACHE模板系统支持NodeJS<br />
  22. 22. Ajaxxx 2011<br />优化内存使用<br />更换模板系统为MUSTACHE<br />使用NodeJS,让页面可以在服务端生成<br />页面组件更加HTC<br />
  23. 23. There AND BACK Again : HTC (HTML Component)<br />Topic 3:<br />
  24. 24. 浏览器内置组件的构成<br />原生的select组件<br />我们开发的select组件<br />按照浏览器构建内置组件的方式构建自定义组件<br />
  25. 25. Microsoft HTC<br />Introduced in Microsoft® Internet Explorer 5, HTML Components (HTCs) provide a mechanism to implement components in script as Dynamic HTML (DHTML) behaviors. <br />
  26. 26. HTC基本架构<br />为自定义组件开发,各自的属性,事件和方法.<br />容器:通过样式中的behavior关联至指定容器对象.<br />属性:通过标签的自定义属性初始化,也可以通过new方法传入的属性初始化<br />方法:开发暴露给使用者的自定义方法<br />事件:直接在标签上订阅事件,或通过脚本注册事件监听<br />事件产生:一般通过事件代理,监听容器内原生键鼠事件,根据触发事件的元素和事件类型,决定是否触发自定义事件.也可以不采用代理的方式直接注册组件内子对象的事件监听,处理较复杂的情况(不冒泡的事件).<br />
  27. 27. Youtube UIX Widget<br />Youtube在VelocityChina介绍<< YouTube的前端性能改进:逐步增强与超越>>其中最重要的UIX Widget系统即是HTC组件开发思想的跨浏览器封装,持续优化实践.<br />
  28. 28. Youtube UIX Widget<br />
  29. 29. Youtube UIX Widget<br />
  30. 30. 我们的实践X-HTC<br />基于YUI3和HTC组件构建思想,开发X-HTC前端组件架构<br />继承YUI3的Base使用YUI3的ATTR管理属性<br />使用<ins>标签关联组件与容器<br />使用mixin的方式区分私有方法集,公共方法集与事件代理方法集<br />组件对象即为YUI3的EventTarget实例,提供自定义事件支持<br />扩展YUI3 Widget对组件生命周期的管理.(initializer, renderUI, bindUI, syncUI, renderData, bindData, destructor)<br />扩展模块属性,解决HTC对其他模块的依赖.<br />提取数据源,以及数据结构对象,每个组件为单一数据结构(List,Tree,Set,Hash)服务,从多数据源获取数据.<br />
  31. 31. X-HTC 解析<br />组件名称<br />属性对象<br />代理事件<br />自定义事件<br />公共方法<br />依赖模块<br />
  32. 32. X-HTC 解析<br />组件解构层次<br />公共方法集mixin<br />事件代理集mixin<br />组件数据绑定<br />数据结构层次<br />
  33. 33. X-HTC 未来<br />减少对YUI3的依赖,更好的控制内存<br />使用mustache模板系统渲染组件<br />适应NodeJS服务端组件生成<br />
  34. 34. FACEBOOK BigPipe++ : STREAMING HTMLstreaming AjaxSTREAMING crossdomain frames <br />Topic 4:<br />
  35. 35. 何时使用Bigpipe<br />Facebook 由于高度定制化,首个请求服务端生成HTML耗时2s以上<br />当页面第一个请求耗时很短时,完全没有必要使用Bigpipe<br />
  36. 36. BigPipe技术要点<br />一.Chunked HTTP:<br />一个HTTP请求可以分段发给发给客户端.<br />PHP中,通过flush(),输出响应片段<br />二.浏览器支持分段解析HTML:<br />chunk1:<br /> <body><br /> <div>先解析先渲染</div><br />chunk2:<br /> <div>后渲染</div><br /> </body><br />
  37. 37. BigPipe实质 : Streaming<br />ChunkedHTTP:让数据分段流动,成为一切Streaming类解决方案的基础.<br />浏览器分段解析:让HTML,JS数据拥有被分段解析的可能<br />Facebook BigPipe<br />chunk1:<br /> <body><br /> <div id=‘pagelete1’/><div id=‘pagelete2’/><br /><script>//pagelet2</script><br /> chunk2:<br /><script>//pagelet1</script><br /> </body><br />
  38. 38. Streaming++<br />Streaming Ajax:<br />使用iframe做Ajax请求,即可做到将异步动态数据逐步流入.<br />这也是长链接(comet)的一种实现方式.<br />
  39. 39. Streaming++<br />Streaming Cross Crossdomainiframe:<br />使用一个iframe做Streaming,利用Dom方法将数据填写到页面其他iframe中.<br />第三方内容依然可以从Streaming受益<br />a.com<br />chunk1<br />b.com:<br />streaming iframe<br />b.com: blank1<br />chunk2<br />b.com: blank2<br />
  40. 40. 客户端无阻滞: 第三方广告代码稳定性和性能优化<br />Topic 5:<br />
  41. 41. 广告影响网页稳定性<br /><script><br />alimama_pid="mm_1_2_3";alimama_type=2; <br />alimama_width=270;alimama_height=390; <br /></script> <br /><script src="http://a.alimama.cn/inf.js"></script><br />inf.js<br />document.write:<br /><iframe(script) src="http://t.alimama.com/a?i=mm_1_1_1<br />&fv=10.1&rd=xyz&u=a.com%2Fa.html"></iframe(script)><br />
  42. 42. 静态脚本阻滞是根源<br />脚本阻滞:HTML中<script>节点对应的脚本下载且执行结束之前,浏览器不会发起任何新的HTTP请求,也不会对该节点以下的任何内容进行渲染.<br />
  43. 43. Script Dom Element<br />使用ScriptDomElement解决脚本阻滞问题<br />function scriptDomElement(u) { <br /> var s = document.createElement('script'),<br /> h = document.getElementsByTagName('head')[0];<br />s.src= u; <br />s.async= true;<br /> if(h)h.insertBefore(s,h.firstChild); <br />} <br />通过Dom方法创建一个script节点,并插入到文档当中.<br />在各种浏览器中这种方式都能保证脚本与其他资源并行下载.<br />
  44. 44. 天生稳定的广告埋点<br /><script><br />document.write('<a style="display:none !important" id="t-a-{id}"></a>');<br />t_h= document.getElementsByTagName('head')[0];<br />t_s= document.createElement('script');<br />t_s.async= true;<br />t_s.src= 'http://{host}/{path}?i={pid}';<br /> if(t_h)t_h.insertBefore(t_s,t_h.firstChild);<br /></script><br />输出占位锚点做位置参照 <a style="display:none !important" id="t-a-{id}"></a><br />异步无阻加载广告数据后,回调函数将广告内容插入到锚点之前.<br />
  45. 45. 老埋点提速改造<br /><script><br />alimama_pid="mm_1_2_3";alimama_type=2; <br />alimama_width=270;alimama_height=390; <br /></script> <br /><script src="http://a.alimama.cn/inf.js"></script><br />
  46. 46. inf.js-3.0<br /><script><br />alimama_pid="mm_1_2_3";alimama_type=2; <br />alimama_width=270;alimama_height=390; <br /></script> <br /><script src="http://anydomain/inf.js"></script><br />
  47. 47. inf.js-3.0<br /><script src="http://anydomain/inf.js"></script><br /><script><br />alimama_pid="mm_1_2_3";alimama_type=2; <br />alimama_width=270;alimama_height=390; <br />window.alimama_show && alimama_show();<br /></script> <br />
  48. 48. inf.js-3.0<br /><!-- http://anydomain/any.js include the content of inf.js --><br /><script src="http://anydomain/any.js"></script><br /><script><br />alimama_pid="mm_1_2_3";alimama_type=2; <br />alimama_width=270;alimama_height=390; <br />window.alimama_show && alimama_show();<br /></script> <br />
  49. 49. inf.js-3.0<br /><script><br /> //content of inf.js<br /></script><br /><script><br />alimama_pid="mm_1_2_3";alimama_type=2; <br />alimama_width=270;alimama_height=390; <br />window.alimama_show && alimama_show();<br /></script> <br />
  50. 50. http://a.com/a.html:<br />alimama_show()<br /><head><br /> <script src="main.js"></script><br /></head><br />异步<br />异步<br />回调<br />异步<br />回调<br /><script src="inf.js"></script><br /><script><br />alimama_show();<br /></script><br /><div><br /> <!-- ad content--><br /></div><br />同步<br /><iframe style="display:none !important" id="anchor-pid"><br /> <!-- ad content--><br /></iframe><br />
  51. 51. Topic 6:<br />severside<br />clientside<br />服务端无阻滞: CommonJSNodeJSCFO(CloSures+Functions+Objects)体系 Web死后jser的未来<br />
  52. 52. 服务端阻滞<br />引擎前端机php使用kfc从其他后台服务获取数据<br />kfc_sendmsg($pg, $msg) <br />//阻滞..线程等待数据返回…<br />$ret = kfc_recvmsg($pg, KFC_SYNC, $timeout);<br />
  53. 53. 更通俗的例子<br />var result = db.query("select..");<br />// use result<br />either blocks the entire process or<br />implies multiple execution stacks.<br />db.query("select..", function (result) {<br /> // use result<br />});<br />allows the program to return to the<br />event loop immediately.<br />
  54. 54. NodeJS<br />node.js : 基于事件驱动的服务端JavaScript<br />优势在于同时处理大量不同类型的I/O<br />通过让所有网络系统I/O无阻塞,让所有文件系统I/O异步化来达到这个目标<br />
  55. 55. NodeJS<br />Node's goal is to provide an easy way to build scalable network programs. many client connections can be handled concurrently. <br />Node tells the operating system (throughepoll, kqueue, /dev/poll, or select) that it should be notified when a new connection is made, and then it goes to sleep. If someone new connects, then it executes the callback.<br />Each connection is only a small heap allocation.<br />
  56. 56. NodeJS性能同类比较<br />100byte响应大小并发与RT关系 300并发响应体大小与RT关系<br />nginxv0.7.65 thinv1.2.7 (ruby 1.9.1-p376)<br />node v0.1.91 tornadov0.2 (python 2.6.4)<br />
  57. 57. TCP By NodeJS<br />var net = require('net'),srv = net.createServer(),socket = null;<br />var onDataArrived = function(data){<br />socket.write(data);<br />};<br />var onConnectSuccess = function(skt){<br />socket = skt;<br />socket.addListener("data",onDataArrived);<br />};<br />srv.addListener("connection",onConnectSuccess);<br />srv.listen(8124, "127.0.0.1");<br />
  58. 58. var net = require('net');<br />net.createServer(<br /> function (socket) {<br />socket.addListener("data", <br /> function (data) {<br />socket.write(data);<br /> }<br /> );<br />}<br />).listen(8124, "127.0.0.1");<br />Add Some Sugar<br />匿名函数<br />函数做参数<br />作用域链<br />链式调用<br />
  59. 59. Why JavaScript ?<br />将服务端基于阻塞的系统改造为事件驱动系统,而GUI系统(如浏览器)多是事件驱动的系统.<br />JavaScript是面向事件驱动系统成熟高效的语言.<br />无需为页面上每个可点击的部件安排一个线程等待点击的发生.<br />
  60. 60. 事件驱动中的状态保持<br />function main(){<br /> var name = "limu";<br /> var age = db.query("selectage from person where name="+name);<br /> print("the age of" + name + "is" + age);<br />}<br />print("query start");<br />main();<br />print时变量name和age同时可用.<br />
  61. 61. 事件驱动中的状态保持<br />function main(){<br /> var name = "limu";<br />db.query("selectage from person where name="+name,<br /> function(age){<br /> print("the age of" + name + "is" + age);<br /> }<br /> );<br />}<br />main();<br />print("query start");<br />假设查询耗时3秒,3秒后执行回调函数.print时age可用.<br />而一般而言name作为main函数的局部变量已经出了其作用域范围而被销毁.<br />如果想继续用name变量需要额外的保存动作,即状态保持.<br />
  62. 62. CFO 体系<br />Understanding this strong relationship between objects, functions, and closures will improve your JavaScript programming ability giving you a strong foundation for any type of application development.<br />
  63. 63. 基于闭包的状态保持<br />function (socket) {<br />socket.addListener("data", <br /> function (data) {<br /> //10s之后data到达本函数运行<br /> //为什么可以访问socket<br />socket.write(data); <br /> }<br />);<br />}<br />闭包:function在生成时会保存所有当时可访问变量的引用,以备函数运行时使用.<br />
  64. 64. CommonJS:JS想成为服务端语言还缺什么<br />Modules<br />Binary strings and buffers<br />Charset encodings<br />Binary, buffered, and textual input and output (io) streams<br />System process arguments, environment, and streams<br />File system interface<br />Socket streams<br />Unit test assertions, running, and reporting<br />Web server gateway interface, JSGI<br />Local and remote packages and package management<br />CommonJS是一种规范,NodeJS是这种规范的部分实现之一。<br />
  65. 65. Web死后Jser的未来<br />由强大的CFO体系支撑:<br />熟练的面向事件驱动系统开发能力<br />无阻塞思想和熟练的异步回调式编码能力<br />熟练的面向对象程序设计能力<br />
  66. 66. 我们的动作<br />为浏览器端JS实现模块化和包管理以及相关的性能优化<br />做异步编程的简化和性能优化<br />在服务端使用NodeJS渲染生成页面的技术,结合Ajaxxx,在不支持JS的浏览器中也能够正常使用Ajaxxx构建的系统.做到一次编码,渐进增强.<br />
  67. 67. JavaScript包管理+模块化:YUI3 & Kissy Vs.KIsssylite<br />Topic 7:<br />PyPI<br />
  68. 68. 第三方广告代码要求<br />必须稳定<br />足够小<br />结构化<br />无限可扩展<br />
  69. 69. kissyLite<br />kissylite,是kissy的一个支持有限方法的子集<br />目标是用1.5k代码支持可扩展的包管理和模块化管理<br />预览地址<br />
  70. 70. ksLite -- 足够小<br />统一风格的OOP,异步的带依赖关系模块化,简单的模板.<br />S.mix<br />S.extend<br />S.clone<br />S.add<br />S.use<br />S.getScript<br />S.substitute<br />
  71. 71. ksLite -- 模块化<br />模块声明<br />S.add(modName,attachFunction,Config);<br />在attachFunction中做类的声明,在Config中指定当前模块所依赖的其他模块.<br />模块使用<br />S.use(modNames,callbackFunction);<br />可以一次使用多个模块,使用时按需载入所需模块,在callbackFunction中即可使用已加载模块中声明的类来生成实例.<br />
  72. 72. KsLite Vs.YUI3 Kissy<br />YUI3 和 Kissy同样提供模块化,但所有模块在use之前必须add.<br />这种模式不满足第三方代码无限可扩展需求.<br />KsLite引入包管理,提高扩展性.<br />
  73. 73. ksLite -- 基于包的扩展<br />包内无限可扩展=> 模块名由包名,路径,文件名.三部分构成.<br />{packagename} - [ {path_0} - ... - {path_n} - ] {filename}<br />S.Config.lt_pkgs={<br />inf:"http://a.alimama.cn/kslite/",<br />test:"http://demo.taobao.com/tbad/kslite/"<br />}<br />模块"inf-a“:http://a.alimama.cn/kslite/inf/a.js<br />模块"test-t-1“: http://demo.taobao.com/tbad/kslite/test/t/1.js<br />
  74. 74. ksLite -- 基于包的扩展<br />可扩展无限包 => package root router<br />在一个地址记录所有可用的包以及对应的class root.<br />S.Config.lt_pkgrouter = http://a.alimama.cn/kslite/router.js<br />S.mix(S.Config.lt_pkgs,{<br /> pkg1:"http://a.alimama.cn/pkg1/",<br /> pkg2:"http://demo.taobao.com/tbad/pkg2/" <br />});<br />当自带S.Config.lt_pkgs没有相关配置时询问pkgrouter.<br />
  75. 75. ksLite -- 命名约定<br />S.add("pkg1-path1-mod1",function(S,P){<br /> S["pkg1"] = S["pkg1"] || {};<br /> P = S["pkg1"];<br />});<br />S.use("pkg1-path1-mod1",function(S,P){});<br />保证包内对象都在名称空间P,即S.P内.<br />相当于另一个途径实现S.app(),嵌入至S的app.<br />为了被Kissy兼容,P只能作为开发约定,手动写在每个包中.<br />
  76. 76. ksLite -- 轻量的add <br />S.add = function(name, fn, config){<br />var mods = S.Env.mods, mod;<br /> if (mods[name] && mods[name].status > INIT)return;<br /> mod = {name: name,fn: fn || null,status: LOADED};<br /> mods[name] = S.mix(mod,config);<br />}<br />不提前attach,保证模块在使用之前没有多余的代码执行消耗.<br />可选优化:domready之前按需执行,domready之后选择性预热. <br />
  77. 77. ksLite -- 简单的use <br />S.use = function(modNames, callback){<br />var mods = S.Env.mods;<br />modNames = modNames.split(',');<br />S.attachMods(modNames, function(){<br /> if (callback) callback(S);<br /> });<br />}<br />将attachMods单独提出来.不止供use中使用.<br />
  78. 78. ksLite – 明确的attachMod<br />如果模块LOADED,直接attach.<br />如果模块没有LOADED,则异步载入模块.然后attach.<br />模块load之后,attach时如果发现requires.<br />attachMods(requires,callbcak).之后attach.<br />
  79. 79. multiAsync加载多个模块<br />S.attachMods = function(modNames,callback){<br />var i, asyncers = {};<br />for (i = 0; i < modNames.length; i++) {<br />asyncers[modNames[i]] = {<br /> f: S.attachMod,<br />a: modNames[i]<br />};<br />}<br />S.multiAsync(asyncers, callback);<br />}<br />
  80. 80. 避免循环引用<br />模块和包都是无限可扩展的,一旦出现循环引用,影响客户页面稳定性<br />场景:<br /> mod-a requires mod-b<br /> mod-b requires mod-c<br />mod-c requires mod-a<br />运行时:<br />S.use("mod-a",function(){});<br />throw new Error("Fatal Error,LoopReqs!");<br />
  81. 81. 简单粗暴的算法<br />在env中有一个对象记录<br />x模块依赖哪些模块<br /> x模块支持哪些模块<br />当出现x依赖x的时候 thorw error. <br />
  82. 82. ksLite的相关问题<br />避免循环引用解决了ksLite可能带来的稳定性隐患<br />遗留问题:<br />串行模块加载的性能问题<br /> attach(模块定义)何时运行的矛盾,提早运行延缓页面初始加载和完全按需运行拖慢事件响应.<br />异步化编程编码方式的简化<br />
  83. 83. Google Closure Compiler 启示 : KISsylite在预编译时间窗口优化性能<br />Topic 8:<br />
  84. 84. D2:Closure Complier<br />在D2论坛,来自Google的Hedger介绍了<<Coding Better Object-Oriented JavaScript with Closure Compiler>><br />Google Closure Complier告诉我们可以在代码发布前增加一个预编译步骤,在此时除了最小化压缩代码之外,编译器配合编码时的一些标准注释提示,来统一OO风格,减小对象深度以提高访问速度,使用枚举,常量等等其他语言好用的特性. <br />
  85. 85. 关于预编译<br />相对于编译型语言,JavaScript缺少了编译这个环节.传统编译器把代码转换为可执行的机器指令的动作交由浏览器中的JS引擎在运行时执行.<br />但现代的编译器除了代码翻译还有哪些功能?而JS引擎能在运行时Cover住这些任务么?<br />最常见的运行时编译无法解决的问题就是代码压缩.所以我们有各种Compressor让代码传输给浏览器的时是最小的. <br />Google Closure Complier解决了另外一些问题.<br />
  86. 86. 预编译打开一扇窗<br />Google Closure Complier更有意义的是告诉我们,可以有这样一个发布前预编译的步骤,可以有这样的一个时间窗口,在这个时候结合我们自己的应用,结合我们自己遇到的问题是不是也可以做点什么.<br />我们在预编译时间窗口解决ksLite遗留的性能相关问题.<br />
  87. 87. 颗粒化的性能问题<br />模块开发者开发一个功能,将它封装在mod-a中. <br />然后我们发现mod-a中可以抽象出来mod-b<br />于是就有了mod-b,同时mod-a requires mod-b.<br />模块使用者根据接口约定S.use("mod-a“,function(S){});<br />拆分前<br />mod-a.js<br />拆分后<br />mod-a.js<br />mod-b.js<br />问题:增加一个请求,而且是串行加载.<br />是否要为可能的重用而进行会引入性能问题的拆分?<br />
  88. 88. 预编译时优化<br />模块开发者不用考虑性能问题,进行最合适的颗粒化.<br />模块使用者在开发期间始终按照接口编码,即S.use("mod-a");<br />编译器建议在发布之前,模块开发者颗粒已确定,模块使用者功能开发完毕,编译时建议此处应该S.use(“mod-a,mod-b”);以便并发加载<br />编译后<br />mod-a.js<br />编译前<br />mod-a.js<br />mod-b.js<br />mod-b.js<br />解决了串行的问题.<br />
  89. 89. 打包策略<br />mod-b可能在mod-a之前使用也可能跟随mod-a引入.<br />如果多数情况mod-b在mod-a之前,那拆分带来好处.<br />如果多数情况mod-b跟随mod-a引入,那mod-b的内容合并至mod-a将会带来好处.<br />应该合并a,b.<br />不应该合并a,b.<br />mod-b.js<br />mod-a.js (include mod-b.js)<br />mod-a.js<br />
  90. 90. 最佳打包实践<br />预编译结合自动化测试可以构建最适合当前应用的打包方案.<br />预编译结合线上使用数据反馈,可以构建最优打包方案.<br />Facebook在Velocity介绍的<<静态资源管理和优化>>,结合Facebook实际数据统计,计算出最优的模块合并方案.<br />
  91. 91. 预加载与延迟加载的矛盾<br />模块add时要不要attach(执行类定义相关代码).<br />即模块add时运行类定义还是use时运行类定义.<br />add时attach:会导致页面加载过程中不必要的代码运行消耗,拖慢页面展现速度.<br />use时attach:会导致事件触发时,由于需要得到模块attach以及可能的依赖模块加载,导致交互事件响应缓慢.<br />
  92. 92. 按需执行+选择性预热<br />add时不attach.优先保证页面展现速度.<br />在DomReady之前,页面展现阶段,只执行需要的代码.<br />在DomReady之后,对页面的交互功能进行预热.<br />页面上有很多功能,应该提前预热哪些?<br />结合重点Case自动化测试用例,预编译可以给出最优的预热方案.<br />S.ready(function(){S.use("mod-b,mod-d,mod-e")});<br />
  93. 93. Jscex 和kslite对异步编码的简化<br />Topic 9:<br />
  94. 94. asyncer -- 异步执行单元<br />/*<br /> * @interface asyncer可能需要等待再回调的function.<br /> * @param { * } args<br />* @param { Function | Object } callback info<br />* @param {number} timeout(ms)<br />* @return {Object}<br /> */<br />function ayncer(args , callback,timeout){ }<br />
  95. 95. parallel asyncers<br />asyncerA(a,function(resA){ <br />window.resA = resA;<br /> if(window.resB)c();<br />});<br />asyncerB(b,function(resB){ <br />window.resB = resB;<br /> if(window.resA)c();<br />})<br />function c(){ <br /> //your code run after resA & resB both returend. <br />}<br />
  96. 96. serial asyncers<br />asyncerA(a,function(resA){ <br />asyncerB(b,function(resB){<br />asyncerC(c,function(resC){<br /> //your code.<br /> })<br /> });<br />});<br />
  97. 97. S.multiAsync<br />S.multiAsync(asyncers,callback,timeout);<br />面向asyncer的interface,通过简单的开发,避免paralleasynce类操作等待其他操作完成时的hardcode.<br />将开发S.serialAsync,避免过多回调造成的作用域链过长而导致的性能下降.<br />
  98. 98. 更先进的异步编程简化<br />Jscex(JavaScript Computation Expressions)由老赵开发,在D2作品秀环节介绍给大家.<br />Jscex让大家以阻塞的模式写代码再经过Jscex实时编译器将代码转化为异步的模式执行.<br />
  99. 99. 更先进的异步编程简化<br />前面的代码编译为下面这段,交给浏览器执行:<br />如果说异步式编程像机器语言一样难写难懂,Jscex将其转化为高级语言一样易于编写和阅读.而ksLite提供的multiAsync和serialAsync则是像汇编语言一样用较少的代码代价对异步编程略微简化,避免一些hardcode,同时解决一些不易处理的性能问题.<br />
  100. 100. Thanks!limu@taobao.comhttp://twitter.com/lenel_li<br />

×