模块加载策略 - 2012 SDCC, 北京

4,238 views

Published on

在北京 2012/9/9 所举办的 SDCC 分享「模块加载策略」

Published in: Technology
0 Comments
15 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,238
On SlideShare
0
From Embeds
0
Number of Embeds
16
Actions
Shares
0
Downloads
80
Comments
0
Likes
15
Embeds 0
No embeds

No notes for slide

模块加载策略 - 2012 SDCC, 北京

  1. 1. 模块加载策略 Module Loader Strategy 讲者 - 蒋定宇 / josephjhttps://speakerdeck.com/u/josephj/p/sdcc
  2. 2. 关于我 - 蒋定宇 (josephj)
  3. 3. 关于我 - 蒋定宇 (josephj) 跑步环岛 ・共 27 天 ・约 900 多公里 2008 年 5 月份
  4. 4. 关于我 - 蒋定宇 (josephj) 跑步环岛 ・共 27 天 ・约 900 多公里 2008 年 5 月份 雅虎奇摩 ・前端工程师 ・YDN 技术布道师 ・主要项目:知识+ 2005.10 - 2009.8
  5. 5. 关于我 - 蒋定宇 (josephj) 跑步环岛 ・共 27 天 ・约 900 多公里 2008 年 5 月份 雅虎奇摩 ・前端工程师 miiiCasa 云永科技 ・YDN 技术布道师 ・主要项目:知识+ ・前端技术团队主管 2005.10 - 2009.8 ・技术布道师 2009.9 至今
  6. 6. 2010.7 两天一夜的北京行留下极深刻的印象
  7. 7. 2010.7 两天一夜的北京行留下极深刻的印象 感谢裕波! 担任讲师 百度参访
  8. 8. 2010.7 两天一夜的北京行留下极深刻的印象 感谢裕波! 担任讲师 当时演讲主题 建立前端开发团队 https://speakerdeck.com/u/josephj/p/webrebuild 百度参访 北京 WebRebuild 演講,收獲滿檔! http://josephj.com/entry.php?id=336
  9. 9. 什么是模块?可以被重复利用的元件
  10. 10. NASA 美国太空总署太空站由 7 个不同国家所提供的 50 多个模块所构成 http://astronomy.wikia.com/wiki/International_Space_Station
  11. 11. NASA 美国太空总署太空站由 7 个不同国家所提供的 50 多个模块所构成 在任何分工精细的工程领域 模块化开发是必然趋势: 「采用既有模块、避免重新打造轮子」 http://astronomy.wikia.com/wiki/International_Space_Station
  12. 12. GitHub
  13. 13. GitHub GitHub 是软体业界的「轮子交流区」git submodule add 就可以轻松加入别人写好的模块
  14. 14. 网页中的模块又是什么? http://www.flickr.com/photos/halfbisqued/2353845688/
  15. 15. 网页中的模块又是什么? 任何可以被载入使用的 HTML、CSS 与 JavaScript 档案 http://www.flickr.com/photos/halfbisqued/2353845688/
  16. 16. 网页中的模块又是什么? 任何可以被载入使用的 HTML、CSS 与 JavaScript 档案 超级好用的两个模块:jQuery 与 Twitter Bootstrap 程序员也可以做出漂亮网站 http://www.flickr.com/photos/halfbisqued/2353845688/
  17. 17. 主题:模块加载策略
  18. 18. 主题:模块加载策略・传统 模式
  19. 19. 主题:模块加载策略・传统 模式・页层级设定 模式 Page-level Setting
  20. 20. 主题:模块加载策略・传统 模式・页层级设定 模式 Page-level Setting・模块层级设定 模式 Module-level Setting
  21. 21. 传统模式
  22. 22. 传统模式用 <link href> 或 <script src> 做加载
  23. 23. 两岸三地的 GitHub 开发者https://github.com/josephj/github-chinese-developer 这次演讲的范例跟工具都在不同的 Branch 中
  24. 24. 两岸三地的 GitHub 开发者https://github.com/josephj/github-chinese-developer 这次演讲的范例跟工具都在不同的 Branch 中
  25. 25. 两岸三地的 GitHub 开发者 https://github.com/josephj/github-chinese-developer 这次演讲的范例跟工具都在不同的 Branch 中 这样的小玩意,肯定大部分人都是直接加载模块的<link href="assets/stylesheets/bootstrap.min.css" rel="stylesheet"> Bootstrap CSS<link href="assets/stylesheets/bootstrap-responsive.css" rel="stylesheet"> Bootstrap CSS<link href="assets/stylesheets/demo.css" rel="stylesheet"> Page CSS<script src="assets/javascripts/jquery-1.8.1.min.js"></script> jQuery<script src="assets/javascripts/handlebars-1.0.0.beta.6.js"></script> Handlebars<script src="assets/javascripts/demo.js"></script> Page JS
  26. 26. 对于一个网站开发团队而言,这样做会陷入混乱 需要一定的开发模式来遵守
  27. 27. 页面模块:一种团队开发模式每个页面模块都切分出 HTML、JavaScript、CSS
  28. 28. 页面模块:一种团队开发模式每个页面模块都切分出 HTML、JavaScript、CSS
  29. 29. 页面模块的 HTML 结构 <div id=”nav”> <div class=”hd”> <h2>標題</h2> </div> <div class=”bd”> <p>內文</p> </div> <div class=”ft”> <a href=”...”>更多... </a> </div> </div>
  30. 30. 页面模块的 HTML 结构 <div id=”nav”> <div class=”hd”> <h2>標題</h2> </div> <div class=”bd”> <p>內文</p> </div> <div class=”ft”> <a href=”...”>更多... </a> </div> </div>
  31. 31. 页面模块的 HTML 结构 <div id=”nav”> <div class=”hd”> <h2>標題</h2> </div>一个 ID 代表一个模块 <div class=”bd”>不能重复 <p>內文</p> </div> <div class=”ft”> <a href=”...”>更多... </a> </div> </div>
  32. 32. 页面模块的 HTML 结构 <div id=”nav”> <div class=”hd”> <h2>標題</h2> </div> .hd, .bd, .ft 代表模块的标一个 ID 代表一个模块 <div class=”bd”> <p>內文</p> 头、内容、标尾结构不能重复 </div> <div class=”ft”> <a href=”...”>更多... </a> </div> </div>
  33. 33. 因每个模块 ID 独立、CSS 不会互相污染 此模块叫 #ykpsb #ykp 是项目缩写、sb 是 Search Box 的縮寫
  34. 34. 因每个模块 ID 独立、CSS 不会互相污染 此模块叫 #ykpsb #ykp 是项目缩写、sb 是 Search Box 的縮寫 form .extra[HTML]<div id=”ykpsb”> <div class=”bd clearfix”> <form ...> ... </form> <div class=”extra”> ... </div> </div></div>
  35. 35. 因每个模块 ID 独立、CSS 不会互相污染 此模块叫 #ykpsb #ykp 是项目缩写、sb 是 Search Box 的縮寫 form .extra[HTML] [CSS]<div id=”ykpsb”> <style> <div class=”bd clearfix”> #ykpsb { <form ...> margin-bottom:10px; ... } </form> #ykpsb form { <div class=”extra”> float:left; ... } </div> #ykpsb .extra { </div> float:right;</div> } </style>
  36. 36. 老道所提的 JavaScript 模块模式window.mods[“ykpsb”] = function () {}();
  37. 37. 老道所提的 JavaScript 模块模式window.mods[“ykpsb”] = function () {    // 利用闭包与外界隔绝    var privateVar,        publicFn;    // 内部自行处理,不会影响其他模块    privateVar = "123";    publicFn = function () {};}();
  38. 38. 老道所提的 JavaScript 模块模式window.mods[“ykpsb”] = function () {    // 利用闭包与外界隔绝    var privateVar,        publicFn;    // 内部自行处理,不会影响其他模块    privateVar = "123";    publicFn = function () {};    return {        // 仅揭露需公开的方法        publicFn: publicFn    };}();
  39. 39. 老道所提的 JavaScript 模块模式window.mods[“ykpsb”] = function () {    // 利用闭包与外界隔绝    var privateVar,        publicFn;    // 内部自行处理,不会影响其他模块    privateVar = "123";    publicFn = function () {};    return {        // 仅揭露需公开的方法        publicFn: publicFn    };}();// 外界仅可存取公开方法mod["ykpsb"].publicFn();
  40. 40. Zakas 的 Scalable JavaScript 模块观察者模式:实作类似 Hub 广播跟监听的行为,达到不使用全域变数跨模组沟通的目的。https://github.com/miiicasa/module Former Principal Front End Engineer, Yahoo! Nicholas Zakas
  41. 41. 发展到一定规模,该如何选择每页所需的模块档呢? 页面模块化会切分出很多零散的档案,如何载入是一门学问 http://www.nipic.com/show/2/55/d96dde66860c5190.html
  42. 42. 发展到一定规模,该如何选择每页所需的模块档呢? 天哪!我该如何处理 这么多模块档案呢? 页面模块化会切分出很多零散的档案,如何载入是一门学问 http://www.nipic.com/show/2/55/d96dde66860c5190.html
  43. 43. 这时我们需要一个 Loader 机制 协助载入零散且多的模块档案 http://www.flickr.com/photos/billjacobus1/123644872/
  44. 44. 页层级设定模式2010 年、北京 WebRebuild 议题之一 https://speakerdeck.com/u/josephj/p/webrebuild
  45. 45. 两岸三地的开发者假设我们用较有规模的「页面模块模式」来开发... http://josephj.com/lab/2012/github-chinese-develope/
  46. 46. 两岸三地的开发者假设我们用较有规模的「页面模块模式」来开发... http://josephj.com/lab/2012/github-chinese-develope/
  47. 47. 两岸三地的开发者 假设我们用较有规模的「页面模块模式」来开发...条件过滤模块 _filter.php _filter.css _filter.js http://josephj.com/lab/2012/github-chinese-develope/
  48. 48. 两岸三地的开发者 假设我们用较有规模的「页面模块模式」来开发...条件过滤模块 _filter.php _filter.css _filter.js 列表模块 _list.php _list.css _list.js http://josephj.com/lab/2012/github-chinese-develope/
  49. 49. 两岸三地的开发者 假设我们用较有规模的「页面模块模式」来开发...条件过滤模块 _filter.php _filter.css _filter.js资讯模块 列表模块 _list.php _info.php _list.css _info.css _info.js _list.js http://josephj.com/lab/2012/github-chinese-develope/
  50. 50. 传统作法肯定会产生悲剧 ・HTTP 请求数量过多 ・会造成页面阻塞 ・档案内容未压缩 ・需用全域变数沟通 ・载入得考虑先后顺序 ・没有清楚的架构、易陷入混乱
  51. 51. MINI 透过设定档将多个檔案合并、最小化 的开发环境工具 https://github.com/josephj/mini http://www.flickr.com/photos/prettypony/2644225789/
  52. 52. Mini 的设定档, 十分容易设定
  53. 53. Mini 的设定档, 十分容易设定 寻找档案的路径,可以设定多个 $DEV_ROOT 是 VirtualHost 的环境变量
  54. 54. Mini 的设定档, 十分容易设定 寻找档案的路径,可以设定多个 $DEV_ROOT 是 VirtualHost 的环境变量 定义 demo 有哪些 CSS 与 JS 档
  55. 55. 指定 type 与 module 即可自动合并且最小化
  56. 56. 指定 type 与 module 即可自动合并且最小化 /mini?module=<module>&type=<css|js>
  57. 57. 指定 type 与 module 即可自动合并且最小化 /mini?module=<module>&type=<css|js>
  58. 58. 没有 Mini 时的情况
  59. 59. 没有 Mini 时的情况
  60. 60. 透过 Mini 可以大幅减少请求数量
  61. 61. 透过 Mini 可以大幅减少请求数量
  62. 62. 由于 Mini 没有缓存机制、只能用在开发环境在 build 时得预先产生合并及最小化后的档案
  63. 63. 由于 Mini 没有缓存机制、只能用在开发环境在 build 时得预先产生合并及最小化后的档案
  64. 64. 由于 Mini 没有缓存机制、只能用在开发环境在 build 时得预先产生合并及最小化后的档案 线上的 CSS/JS 在 Build 后成为单一档案
  65. 65. 页层级设定模式的整体架构
  66. 66. 页层级设定模式的整体架构很直觉的载入机制,可以有效地将模块档案合并压缩
  67. 67. 页层级设定模式这是 miiiCasa 从一开始就使用的模块加载方式 网站上线后都很稳定、很满意 但随著几次的改版,我們發现了不少问题
  68. 68. 缺点 - 维护不易改版必定伴随著模块 (功能) 的新增、修改、移除 修改 Mini 的组态设定不就好了吗?
  69. 69. 缺点 - 维护不易改版必定伴随著模块 (功能) 的新增、修改、移除 修改 Mini 的组态设定不就好了吗? 改版到新版后,有 3 个页面模块需要移除 (基本就有 9 个档案需移除)
  70. 70. 但模块依赖关系是非常复杂的! http://www.flickr.com/photos/kalavinka/4617897952/
  71. 71. 但模块依赖关系是非常复杂的! http://www.flickr.com/photos/kalavinka/4617897952/
  72. 72. 但模块依赖关系是非常复杂的! 页面模块 JavaScript http://www.flickr.com/photos/kalavinka/4617897952/
  73. 73. 但模块依赖关系是非常复杂的! 功能模块 JavaScript 页面模块 JavaScript http://www.flickr.com/photos/kalavinka/4617897952/
  74. 74. 但模块依赖关系是非常复杂的! YUI CSS 页面模块 CSS 功能模块 JavaScript 页面模块 JavaScript http://www.flickr.com/photos/kalavinka/4617897952/
  75. 75. 但模块依赖关系是非常复杂的! YUI CSS 页面模块 CSS 功能模块 JavaScript 想要移除一个页面模块 哪些功能模块也需要一起移除呢? 页面模块 JavaScript http://www.flickr.com/photos/kalavinka/4617897952/
  76. 76. 解决依赖问题,最近很火热的 AMD 架构
  77. 77. 解决依赖问题,最近很火热的 AMD 架构 // 定义⼀一个 AMD 模块 define(“editor”, [“handlebars”], function () { 6006 Constructor */ }     function Editor { /*     return Editor; },);
  78. 78. 解决依赖问题,最近很火热的 AMD 架构 // 定义⼀一个 AMD 模块 define(“editor”, [“handlebars”], function () { 6006 Constructor */ }     function Editor { /*     return Editor; },); 第二个参数可以定义此模块需要哪些模块
  79. 79. 解决依赖问题,最近很火热的 AMD 架构 // 定义⼀一个 AMD 模块 define(“editor”, [“handlebars”], function () { 6006 Constructor */ }     function Editor { /*     return Editor; },); 第二个参数可以定义此模块需要哪些模块 // 使用⼀一个 AMD 模块 require(["editor"], function (Editor) {     new Editor(); 6006 }); 在使用时以动态载入方式将相关模块档案一并载入
  80. 80. 缺点 - Build 耗时过久我们共有这么多的页面需预先 Build:
  81. 81. 缺点 - Build 耗时过久我们共有这么多的页面需预先 Build:
  82. 82. 缺点 - Build 耗时过久我们共有这么多的页面需预先 Build: miiiCasa Build 流程中 得为所有页面建置静态档 此单项作业得耗时 2 分半!
  83. 83. 缺点 - Build 耗时过久我们共有这么多的页面需预先 Build: miiiCasa Build 流程中 得为所有页面建置静态档 此单项作业得耗时 2 分半! 但是持续整合的标准是 完整 Build 不应超过 10 分钟
  84. 84. 缺点 - 线上除虫困难
  85. 85. 缺点 - 线上除虫困难即使经过 Beautifier 仍不易修改、还是得 Build、对要求敏捷开发就差了些
  86. 86. 缺点 - 缓存效率差每页的 JS 与 CSS 档案都是完全不重复的 也因此没有办法做到跨页间的缓存
  87. 87. 缺点 - 缓存效率差 两页有许多共用的页面模块、却无缓存的好处miii_index_my_contact_34945d9e0efb63c7dc62dcbbc3442a60.css miii_index_my_device_623f7e30575a7180ddeb11fd748aed31.cssmiii_index_my_contact_18fa331dfbf2bd392660925ba8f41239.js miii_index_my_device_704b3ae3682d178a94465c066b0f6d42.js 后来我们为了缓存、抽离出一些共用 Mini 模块 但这样做反而让设定更难易维护
  88. 88. 模块层级设定模式 真正的模块导向开发!
  89. 89. 我心目中的乌托邦! 让模块化开发不需要再有烦恼页面配置!
  90. 90. 我心目中的乌托邦! 让模块化开发不需要再有烦恼页面配置!
  91. 91. 我心目中的乌托邦! 让模块化开发不需要再有烦恼页面配置! 模块架构 开发者专注于单一模块的开发 设定此模块需要哪些依赖模块
  92. 92. 我心目中的乌托邦! 让模块化开发不需要再有烦恼页面配置! 模块架构 开发者专注于单一模块的开发 设定此模块需要哪些依赖模块 模块 Loader Loader 计算出页面 有哪些模块需载入
  93. 93. 我心目中的乌托邦! 让模块化开发不需要再有烦恼页面配置! 模块架构 开发者专注于单一模块的开发 设定此模块需要哪些依赖模块 模块 Loader Loader 计算出页面 有哪些模块需载入 远端模块载入机制 服务器与浏览器端交互配合 自动以效能最佳化方式载入远端模块
  94. 94. RequireJS 是目前最牛逼的 AMD 实作
  95. 95. RequireJS 是目前最牛逼的 AMD 实作 // AMD Module define(“editor”, [‘a’,’b’,’c’], function () {     function Editor { /* Constructor */ }     return Editor; }); require(["editor"], function (Editor) {     new Editor(); }); 可以自动一个一个载入依赖的模块 或发布前透过 r.js 做合并及最小化
  96. 96. RequireJS 是目前最牛逼的 AMD 实作 合并与最小化仍然会有线上除错困难与 Build 时间过久的两个问题、 // AMD Module define(“editor”, [‘a’,’b’,’c’], function () { 甚至模块一多对开发速度也会造成冲击     function Editor { /* Constructor */ }     return Editor; }); require(["editor"], function (Editor) { RequireJS 的架构因此不太符合我的需求     new Editor(); }); 可以自动一个一个载入依赖的模块 或发布前透过 r.js 做合并及最小化
  97. 97. 国内较少人使用的 YUI 函式库
  98. 98. 国内较少人使用的 YUI 函式库早在三年前、2009/6 月就提出的模块架构
  99. 99. 国内较少人使用的 YUI 函式库 早在三年前、2009/6 月就提出的模块架构// AMD Moduledefine(‘editor’, [‘a’,’b’,’c’], function() {    function Editor { /* Constructor */ }    return Editor;});require(["editor"], function (Editor) {    new Editor();});
  100. 100. 国内较少人使用的 YUI 函式库 早在三年前、2009/6 月就提出的模块架构 // AMD Module // YUI Module define(‘editor’, [‘a’,’b’,’c’], function YUI.add("editor", function () { () {     function Editor { /* Constructor */ }     function Editor { /* Constructor */ }     Y.Editor = Editor;         return Editor; }, “VERSION”, {requires:[‘a’,’b’,’c’]}); }); YUI.use("editor", function (Y) { require(["editor"], function (Editor) {     new Y.Editor();     new Editor(); }); });跟去年才有的 AMD、所要解决模块依赖性的思路是一致的
  101. 101. 以 YUI DataTable 为范例
  102. 102. 以 YUI DataTable 为范例
  103. 103. 以 YUI DataTable 为范例 不 Reload 的行为很多: 换页、排序、直接编辑。也 可以接受各类资料来源,是 很复杂的模组
  104. 104. 只要几行代码就可以载入所需模块
  105. 105. 只要几行代码就可以载入所需模块<script src="http://yui.yahooapis.com/3.5.0/build/yui/yui-min.js"></script>
  106. 106. 只要几行代码就可以载入所需模块<script src="http://yui.yahooapis.com/3.5.0/build/yui/yui-min.js"></script><script>YUI().use(datatable, function (Y) {        });</script>
  107. 107. 只要几行代码就可以载入所需模块<script src="http://yui.yahooapis.com/3.5.0/build/yui/yui-min.js"></script><script>YUI().use(datatable, function (Y) {        alert(Y.DataTable);});</script> 能想像 6 行代码背后,做了多少事情吗?
  108. 108. 计算所需模块的流程 yui (Seed)
  109. 109. 计算所需模块的流程 YUI().use(datatable) yui (Seed)
  110. 110. 计算所需模块的流程datatable-core datatable-head datatable-body base-build widget YUI().use(datatable) yui (Seed)
  111. 111. 计算所需模块的流程escape node-base base-plugin-host node-style model-list base-base event-focus viewnode-event-delegate classnamemanager attributedatatable-core datatable-head datatable-body base-build widget YUI().use(datatable) yui (Seed)
  112. 112. 计算所需模块的流程arraylist yui-base pluginhost event-synthetic attribute-core attribute-events model event-delegate attribute-extras array-extras array-invoke json-parse escape node-base base-plugin-host node-style model-list base-base event-focus view node-event-delegate classnamemanager attribute datatable-core datatable-head datatable-body base-build widget YUI().use(datatable) yui (Seed)
  113. 113. 计算所需模块的流程arraylist yui-base pluginhost event-synthetic attribute-core attribute-events model event-delegate attribute-extras array-extras array-invoke json-parse 实际上 datatable 共有 64 個模块档需载入 escape node-base base-plugin-host node-style 一个一个载入会很操效能 model-list base-base event-focus view YUI 的处理方式为何? node-event-delegate classnamemanager attribute datatable-core datatable-head datatable-body base-build widget yui (Seed) YUI().use(datatable)
  114. 114. 强大的压缩机 Combo
  115. 115. 强大的压缩机 Combo 雅虎的 Combo 机制直接以 GET 参数将不同模块档案串连并最小化
  116. 116. 强大的压缩机 Combo 雅虎的 Combo 机制直接以 GET 参数将不同模块档案串连并最小化http://yui.yahooapis.com/combo? <模块 1 的对应路径>& <模块 2 的对应路径>& <模块 3 的对应路径>& ... <模块 n 的对应路径>
  117. 117. 并行非堵塞加载YUI().use(datatable)
  118. 118. 并行非堵塞加载 YUI().use(datatable)YUI 种子档案
  119. 119. 并行非堵塞加载 YUI().use(datatable)YUI 种子档案 载入相关 CSS
  120. 120. 并行非堵塞加载 YUI().use(datatable)YUI 种子档案 载入相关 CSS 将所需 JavaScript 模块分散请求、并行下载
  121. 121. 并行非堵塞加载 YUI().use(datatable)YUI 种子档案 载入相关 CSS 将所需 JavaScript 模块分散请求、并行下载分散与 Combo 逻辑考虑了:「模块先后顺序」、「模块数量」、「浏览器同时请求数量」、「浏览器 GET 长度限制」,非常的自动化。自己要做这样的机制非常不易。
  122. 122. YUI().use(datatable)
  123. 123. 从种子变成大树仅花了 323msYUI().use(datatable) 323ms
  124. 124. 从种子变成大树仅花了 323msYUI().use(datatable) 323ms 不了解内情的人会说 YUI 很肥很庞大 实际上它只载入需要的模块、其他函式库沒有這樣的效率
  125. 125. 从种子变成大树仅花了 323msYUI().use(datatable) 323ms 不了解内情的人会说 YUI 很肥很庞大 实际上它只载入需要的模块、其他函式库沒有這樣的效率 例如:使用 jQuery 真的每页都用的到 ajax 这个函式吗?
  126. 126. YUI 载入方式实在太 Sexy 了、应被大力推广! The creator of jQueryJohn Resig http://www.quora.com/How-could-YUI3-improve-its-image-compared-to-jQuery-MooTools-etc
  127. 127. YUI 载入方式实在太 Sexy 了、应被大力推广! YUI().use() + pulling code off of Yahoos CDN is damn sexy and should be promoted *VERY* heavily. The creator of jQueryJohn Resig http://www.quora.com/How-could-YUI3-improve-its-image-compared-to-jQuery-MooTools-etc
  128. 128. YUI 的架构正是我所期盼的 有模块架构、有模块 Loader、 配合最佳化的远端模块载入机制!还等什么?快到用在网站页面模块的载入机制上!
  129. 129. 问题:寻找 Combo 机制的替代品
  130. 130. 问题:寻找 Combo 机制的替代品雅虎的 Combo 仅供内部使用、还好有人写了替代品!我选择的是 Minify 这个工具,一样会帮我做伺服器端的缓存、合并与档案最小化
  131. 131. 问题:寻找 Combo 机制的替代品雅虎的 Combo 仅供内部使用、还好有人写了替代品!我选择的是 Minify 这个工具,一样会帮我做伺服器端的缓存、合并与档案最小化 Minify (PHP5) http://code.google.com/p/minify/ https://github.com/mrclay/minify
  132. 132. 问题:寻找 Combo 机制的替代品雅虎的 Combo 仅供内部使用、还好有人写了替代品!我选择的是 Minify 这个工具,一样会帮我做伺服器端的缓存、合并与档案最小化 Minify (PHP5) http://<your host>/minify?f= <模块 1 的对应路径>, <模块 2 的对应路径>, ... <模块 n 的对应路径> http://code.google.com/p/minify/ https://github.com/mrclay/minify
  133. 133. 困难二:YUI 自订模块组态设定复杂
  134. 134. 困难二:YUI 自订模块组态设定复杂非 YUI 本身的模块得另外定义,但这样不好维护
  135. 135. 困难二:YUI 自订模块组态设定复杂 非 YUI 本身的模块得另外定义,但这样不好维护YUI_config = {"filter":"raw","async":true,"combine":true,"comboBase":"combo/?f=","comboSep":",","root":"lib/yui/build/","langs":"zh-TW,en-US","groups":{"mui":{"combine":true,"fetchCSS":true,"root":"lib/mui/","lang":["en-US","zh-TW"],"modules":{"platform-core":{"path":"platform/core.js","requires":["node-base","event-base","platform-sandbox"]},"platform-sandbox":{"path":"platform/sandbox.js"},"lang-service":{"path":"platform/lang_service.js","requires":["platform-core","platform-sandbox","intl"]},"scroll-pagination":{"path":"scroll-pagination/scroll-pagination.js","requires":["event","event-resize","node-event-delegate","datasource","scroll-pagination-css"]},"scroll-pagination-css":{"path":"scroll-pagination/assets/scroll-pagination.css","type":"css"},"shjs":{"path":"shjs/sh_php.min.js","requires":["shjs-core","shjs-css"]},"shjs-css":{"path":"shjs/sh_nedit.css","type":"css"},"mui-cssbutton":{"path":"cssbutton/assets/skins/miiicasa/cssbutton-skin.css","type":"css"},"shjs-core":{"path":"shjs/sh_main.min.js"}}},"index":{"combine":true,"fetchCSS":false,"root":"index/","lang":["en-US","zh-TW"],"modules":{"welcome":{"path":"welcome/welcome.js","lang":["en-US","zh-TW"],"requires":["platform-core","platform-sandbox","lang-service","console"]},"welcome/_notification":{"path":"welcome/_notification.js","requires":["substitute","scroll-pagination","yql","panel","node-event-delegate","handlebars"]},"charming/_masthead":{"path":"charming/_masthead.js","requires":["panel","shjs"]},"common/_sidebar":{"requires":["mui-cssbutton"]}}}}};YUI().use("welcome","welcome/_notification","charming/_masthead","common/_sidebar");
  136. 136. 困难三:CSS 不适用于动态加载
  137. 137. 困难三:CSS 不适用于动态加载YUI 与 RequireJS 都可以加载 CSS、 但都只能采用动态加载
  138. 138. 困难三:CSS 不适用于动态加载 YUI 与 RequireJS 都可以加载 CSS、 但都只能采用动态加载 CSS 须在 HTML 显示前就准备好,不然浏览器须一直重新绘制,对网站效能会是很大的冲击
  139. 139. 困难三:CSS 不适用于动态加载 YUI 与 RequireJS 都可以加载 CSS、 但都只能采用动态加载 CSS 须在 HTML 显示前就准备好,不然浏览器须一直重新绘制,对网站效能会是很大的冲击 <link rel="stylesheet" href="page.css" media="all">
  140. 140. YUI 解决了大部分的需求 剩下的桥梁得自己建设!http://www.flickr.com/photos/defenceimages/6771187177/
  141. 141. YUI 解决了大部分的需求 剩下的桥梁得自己建设! https://github.com/josephj/static-loader 一并解决 YUI 组态的复杂度与 让 CSS 传统加载http://www.flickr.com/photos/defenceimages/6771187177/
  142. 142. 两岸三地的开发者 这回我们要加上模块依赖关系!条件过滤模块 _filter.php _filter.css _filter.js资讯模块 列表模块 _info.php _list.php _info.css _list.css _info.js _list.js http://josephj.com/lab/2012/github-chinese-develope/
  143. 143. 两岸三地的开发者 module, 这回我们要加上模块依赖关系! cookie条件过滤模块 _filter.php _filter.css _filter.js • module资讯模块 列表模块 • node-event-delegate _info.php _list.php • node-style _info.css _list.css • node-screen _info.js _list.js • cache • jsonp• module • handlebars• node-base • event-resize• handlebars • cookie http://josephj.com/lab/2012/github-chinese-develope/
  144. 144. 每个模块的组态设定不再維護類似 Mini 的頁面設定
  145. 145. 每个模块的组态设定不再維護類似 Mini 的頁面設定
  146. 146. 每个模块的组态设定不再維護類似 Mini 的頁面設定 模块定义自身 JS 与 CSS 位置 及依赖关系
  147. 147. 指定此页面有哪些页面模块 很直觉的指定方式
  148. 148. 指定此页面有哪些页面模块 很直觉的指定方式
  149. 149. 指定此页面有哪些页面模块 很直觉的指定方式 不需知道背後的依賴模塊!只要指定页面模块 移除也不需要担心影响别的模块
  150. 150. 轻易将所有需要的设定与标签输出 复杂的事情应该交给程式来做啊!
  151. 151. 轻易将所有需要的设定与标签输出 复杂的事情应该交给程式来做啊!
  152. 152. 轻易将所有需要的设定与标签输出 复杂的事情应该交给程式来做啊!
  153. 153. 加载的方式十分优异
  154. 154. 加载的方式十分优异 以传统方式加载种子与页面 CSS
  155. 155. 加载的方式十分优异 以传统方式加载种子与页面 CSS 分散並發的 JS 请求 是自动计算依赖关系而生成
  156. 156. 未来开发可以完全专注在模块上
  157. 157. 未来开发可以完全专注在模块上A. 通知讯息模块 (_notification) 模块开发者 A 模块名称 welcome/_notification CSS 档案 welcome/_notification.css JS 档案 welcome/_notification.js 相依模块 scroll-pagination, node-event-delegate, viewer
  158. 158. 未来开发可以完全专注在模块上 A. 通知讯息模块 (_notification) 模块开发者 A 模块名称 welcome/_notification CSS 档案 welcome/_notification.css JS 档案 welcome/_notification.js 相依模块 scroll-pagination, node-event-delegate, viewerB. 页首模块 (_masthead) 模块开发者 B 模块名称 common/_masthead CSS 档案 common/_masthead.css JS 档案 common/_masthead.js 所需模块 panel, device-navigation
  159. 159. 未来开发可以完全专注在模块上 A. 通知讯息模块 (_notification) 模块开发者 A 模块名称 welcome/_notification CSS 档案 welcome/_notification.css JS 档案 welcome/_notification.js 相依模块 scroll-pagination, node-event-delegate, viewerB. 页首模块 (_masthead) C. 侧边栏模块 (_sidebar) 模块开发者 B 模块开发者 C 模块名称 common/_masthead CSS 档案 common/_masthead.css 模块名称 welcome/_sidebar JS 档案 common/_masthead.js CSS 档案 welcome/_sidebar.css 所需模块 panel, device-navigation JS 档案 無 所需模块 無
  160. 160. 最后再 Controller 指定页面模块即可 页面开发者 登入后首页 (welcome.php)
  161. 161. 最后再 Controller 指定页面模块即可 页面开发者 登入后首页 (welcome.php)此页面有以下模块:·•welcome/_notification·•charming/_masthead·•common/_sidebar
  162. 162. 回顧页层级设定所遭遇的困难
  163. 163. 回顧页层级设定所遭遇的困难・ Build 效率问题 不再 Build,由 Minify 在线上自动合并、压缩、版本控管。
  164. 164. 回顧页层级设定所遭遇的困难・ Build 效率问题 不再 Build,由 Minify 在线上自动合并、压缩、版本控管。・ 线上除错问题 原始档案皆存在,可以直接修正问题,只要把 Minify 对应的缓存砍掉即可
  165. 165. 回顧页层级设定所遭遇的困难・ Build 效率问题 不再 Build,由 Minify 在线上自动合并、压缩、版本控管。・ 线上除错问题 原始档案皆存在,可以直接修正问题,只要把 Minify 对应的缓存砍掉即可・ 维护性问题 開發者只定义自身模块的相依性、整页所需模塊由 YUI Loader 計算後自動載 入,管理容易许多。
  166. 166. 回顧页层级设定所遭遇的困难・ Build 效率问题 不再 Build,由 Minify 在线上自动合并、压缩、版本控管。・ 线上除错问题 原始档案皆存在,可以直接修正问题,只要把 Minify 对应的缓存砍掉即可・ 维护性问题 開發者只定义自身模块的相依性、整页所需模塊由 YUI Loader 計算後自動載 入,管理容易许多。・ 共用的缓存问题 除了全域共用采用 Minify 中的 groupConfig,其馀不处理、避免维护问题
  167. 167. 结语
  168. 168. 结语 页层级的设置可想成「中央集权」设置容易。初期一目了然,但规模变大就管理不易。
  169. 169. 结语 页层级的设置可想成「中央集权」设置容易。初期一目了然,但规模变大就管理不易。 模块层级設定则是「地方自治」 设置较复杂、对长期维护较有效率。配合相依性计算、自动合并、非同步下载等机制 让页面模块真的做到随插即用
  170. 170. 结语
  171. 171. 结语 BigPipe 是很多网站想实作的目标但首先你得「建立模块相依性」、「采用页面模块开发模式」 先建立模块导向开发模式才可能有实作的机会 鼓励较具规模的网站开始往这方向移动
  172. 172. 相关连结 今天看到的所有程式码或工具都是可分享的!・2010 建立前端开发团队 (http://www.slideshare.net/sdcc)・跨模块沟通机制 (http://github.com/miiicasa/module)・Mini 加载工具 (http://github.com/josephj/mini)・模块加载机制 (http://github.com/josephj/static-loader)・两岸三地的 GitHub 开发者 (http://github.com/josephj/github-chinese-develop)・我的博客:这样做就对了 (http://josephj.com)・我的 Email:josephj6802@gmail.com
  173. 173. Questions?
  174. 174. miiiCasa 家庭雲、建立家中的 SNS!在北京工作的⼀一家人
  175. 175. miiiCasa 家庭雲、建立家中的 SNS! 在老家重慶的奶奶在北京工作的⼀一家人
  176. 176. miiiCasa 家庭雲、建立家中的 SNS! 位於家中、可存放照片的分享器 在老家重慶的奶奶在北京工作的⼀一家人
  177. 177. miiiCasa 家庭雲、建立家中的 SNS! 位於家中、可存放照片的分享器 在老家重慶的奶奶 互连网在北京工作的⼀一家人
  178. 178. miiiCasa 家庭雲、建立家中的 SNS! 位於家中、可存放照片的分享器 在老家重慶的奶奶 互连网在北京工作的⼀一家人 想看孫女只要换个频道就可以了

×