179
模块加载策略 讲者 - 蒋定宇 / josephj https://speakerdeck.com/u/josephj/p/sdcc Module Loader Strategy

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

Embed Size (px)

DESCRIPTION

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

Citation preview

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

模块加载策略

讲者 - 蒋定宇 / josephj

https://speakerdeck.com/u/josephj/p/sdcc

Module Loader Strategy

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

关于我 - 蒋定宇 (josephj)

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

关于我 - 蒋定宇 跑步环岛

·共 27 天·约 900 多公里

2008 年 5 月份

(josephj)

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

关于我 - 蒋定宇

雅虎奇摩

·前端工程师·YDN 技术布道师·主要项目:知识+

跑步环岛

·共 27 天·约 900 多公里

2008 年 5 月份

2005.10 - 2009.8

(josephj)

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

关于我 - 蒋定宇

雅虎奇摩

·前端工程师·YDN 技术布道师·主要项目:知识+

miiiCasa 云永科技

·前端技术团队主管·技术布道师

跑步环岛

·共 27 天·约 900 多公里

2008 年 5 月份

2005.10 - 2009.8

2009.9 至今

(josephj)

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

2010.7 两天一夜的北京行留下极深刻的印象

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

2010.7 两天一夜的北京行留下极深刻的印象

担任讲师感谢裕波!

百度参访

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

2010.7 两天一夜的北京行留下极深刻的印象

担任讲师感谢裕波!

百度参访

http://josephj.com/entry.php?id=336

北京 WebRebuild 演講,收獲滿檔!

https://speakerdeck.com/u/josephj/p/webrebuild

建立前端开发团队当时演讲主题

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

什么是模块?可以被重复利用的元件

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

由 7 个不同国家所提供的 50 多个模块所构成

http://astronomy.wikia.com/wiki/International_Space_Station

NASA 美国太空总署太空站

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

由 7 个不同国家所提供的 50 多个模块所构成

http://astronomy.wikia.com/wiki/International_Space_Station

NASA 美国太空总署太空站

在任何分工精细的工程领域

模块化开发是必然趋势:

「采用既有模块、避免重新打造轮子」

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

GitHub

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

GitHubGitHub 是软体业界的「轮子交流区」

git submodule add 就可以轻松加入别人写好的模块

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

http://www.flickr.com/photos/halfbisqued/2353845688/

网页中的模块又是什么?

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

http://www.flickr.com/photos/halfbisqued/2353845688/

任何可以被载入使用的 HTML、CSS 与 JavaScript 档案

网页中的模块又是什么?

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

http://www.flickr.com/photos/halfbisqued/2353845688/

任何可以被载入使用的 HTML、CSS 与 JavaScript 档案

超级好用的两个模块:jQuery 与 Twitter Bootstrap

网页中的模块又是什么?

程序员也可以做出漂亮网站

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

主题:模块加载策略

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

主题:模块加载策略

·传统 模式

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

主题:模块加载策略

·传统 模式

·页层级设定 模式 Page-level Setting

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

主题:模块加载策略

·传统 模式

·页层级设定 模式 Page-level Setting

·模块层级设定 模式 Module-level Setting

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

传统模式

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

传统模式用 <link href> 或 <script src> 做加载

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

两岸三地的 GitHub 开发者https://github.com/josephj/github-chinese-developer

这次演讲的范例跟工具都在不同的 Branch 中

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

两岸三地的 GitHub 开发者https://github.com/josephj/github-chinese-developer

这次演讲的范例跟工具都在不同的 Branch 中

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

两岸三地的 GitHub 开发者https://github.com/josephj/github-chinese-developer

这次演讲的范例跟工具都在不同的 Branch 中

<link href="assets/stylesheets/bootstrap.min.css" rel="stylesheet"><link href="assets/stylesheets/bootstrap-responsive.css" rel="stylesheet"><link href="assets/stylesheets/demo.css" rel="stylesheet">

<script src="assets/javascripts/jquery-1.8.1.min.js"></script><script src="assets/javascripts/handlebars-1.0.0.beta.6.js"></script>

<script src="assets/javascripts/demo.js"></script>

这样的小玩意,肯定大部分人都是直接加载模块的Bootstrap CSS

Bootstrap CSS

Page CSS

jQuery

Handlebars

Page JS

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

对于一个网站开发团队而言,这样做会陷入混乱

需要一定的开发模式来遵守

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

页面模块:一种团队开发模式每个页面模块都切分出 HTML、JavaScript、CSS

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

页面模块:一种团队开发模式每个页面模块都切分出 HTML、JavaScript、CSS

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

<div id=”nav”> <div class=”hd”> <h2>標題</h2> </div> <div class=”bd”> <p>內文</p> </div> <div class=”ft”> <a href=”...”>更多... </a> </div></div>

页面模块的 HTML 结构

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

<div id=”nav”> <div class=”hd”> <h2>標題</h2> </div> <div class=”bd”> <p>內文</p> </div> <div class=”ft”> <a href=”...”>更多... </a> </div></div>

<div id=”nav”> <div class=”hd”> <h2>標題</h2> </div> <div class=”bd”> <p>內文</p> </div> <div class=”ft”> <a href=”...”>更多... </a> </div></div>

页面模块的 HTML 结构

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

<div id=”nav”> <div class=”hd”> <h2>標題</h2> </div> <div class=”bd”> <p>內文</p> </div> <div class=”ft”> <a href=”...”>更多... </a> </div></div>

<div id=”nav”> <div class=”hd”> <h2>標題</h2> </div> <div class=”bd”> <p>內文</p> </div> <div class=”ft”> <a href=”...”>更多... </a> </div></div>

页面模块的 HTML 结构

一个 ID 代表一个模块

不能重复

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

<div id=”nav”> <div class=”hd”> <h2>標題</h2> </div> <div class=”bd”> <p>內文</p> </div> <div class=”ft”> <a href=”...”>更多... </a> </div></div>

<div id=”nav”> <div class=”hd”> <h2>標題</h2> </div> <div class=”bd”> <p>內文</p> </div> <div class=”ft”> <a href=”...”>更多... </a> </div></div>

页面模块的 HTML 结构

一个 ID 代表一个模块

不能重复

.hd, .bd, .ft 代表模块的标

头、内容、标尾结构

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

因每个模块 ID 独立、CSS 不会互相污染此模块叫 #ykpsb

#ykp 是项目缩写、sb 是 Search Box 的縮寫

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

<div id=”ykpsb”> <div class=”bd clearfix”> <form ...> ... </form> <div class=”extra”> ... </div> </div></div>

form .extra

[HTML]

因每个模块 ID 独立、CSS 不会互相污染此模块叫 #ykpsb

#ykp 是项目缩写、sb 是 Search Box 的縮寫

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

<div id=”ykpsb”> <div class=”bd clearfix”> <form ...> ... </form> <div class=”extra”> ... </div> </div></div>

form .extra

[HTML]<style>#ykpsb { margin-bottom:10px;}#ykpsb form { float:left;}#ykpsb .extra { float:right;}</style>

[CSS]

因每个模块 ID 独立、CSS 不会互相污染此模块叫 #ykpsb

#ykp 是项目缩写、sb 是 Search Box 的縮寫

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

老道所提的 JavaScript 模块模式

window.mods[“ykpsb”] = function () {

}();

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

老道所提的 JavaScript 模块模式

window.mods[“ykpsb”] = function () {

}();

    // 利用闭包与外界隔绝    var privateVar,        publicFn;

    // 内部自行处理,不会影响其他模块    privateVar = "123";

    publicFn = function () {};

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

老道所提的 JavaScript 模块模式

window.mods[“ykpsb”] = function () {

}();

    // 利用闭包与外界隔绝    var privateVar,        publicFn;

    // 内部自行处理,不会影响其他模块    privateVar = "123";

    publicFn = function () {};

    return {        // 仅揭露需公开的方法        publicFn: publicFn    };

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

老道所提的 JavaScript 模块模式

window.mods[“ykpsb”] = function () {

}();

    // 利用闭包与外界隔绝    var privateVar,        publicFn;

    // 内部自行处理,不会影响其他模块    privateVar = "123";

    publicFn = function () {};

    return {        // 仅揭露需公开的方法        publicFn: publicFn    };

// 外界仅可存取公开方法mod["ykpsb"].publicFn();

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

Nicholas ZakasFormer Principal Front End Engineer, Yahoo!

Zakas 的 Scalable JavaScript 模块

观察者模式:

实作类似 Hub 广播跟监听的行为,达到不使用全域变数跨模组沟通的目的。

https://github.com/miiicasa/module

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

http://www.nipic.com/show/2/55/d96dde66860c5190.html

发展到一定规模,该如何选择每页所需的模块档呢?

页面模块化会切分出很多零散的档案,如何载入是一门学问

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

http://www.nipic.com/show/2/55/d96dde66860c5190.html

天哪!我该如何处理

这么多模块档案呢?

发展到一定规模,该如何选择每页所需的模块档呢?

页面模块化会切分出很多零散的档案,如何载入是一门学问

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

http://www.flickr.com/photos/billjacobus1/123644872/

这时我们需要一个 Loader 机制协助载入零散且多的模块档案

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

http://josephj.com/lab/2012/github-chinese-develope/

两岸三地的开发者假设我们用较有规模的「页面模块模式」来开发...

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

两岸三地的开发者假设我们用较有规模的「页面模块模式」来开发...

http://josephj.com/lab/2012/github-chinese-develope/

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

两岸三地的开发者

条件过滤模块 _filter.php _filter.css _filter.js

假设我们用较有规模的「页面模块模式」来开发...

http://josephj.com/lab/2012/github-chinese-develope/

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

两岸三地的开发者

列表模块_list.php_list.css_list.js

条件过滤模块 _filter.php _filter.css _filter.js

假设我们用较有规模的「页面模块模式」来开发...

http://josephj.com/lab/2012/github-chinese-develope/

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

两岸三地的开发者

资讯模块 列表模块_info.php_info.css_info.js

_list.php_list.css_list.js

条件过滤模块 _filter.php _filter.css _filter.js

假设我们用较有规模的「页面模块模式」来开发...

http://josephj.com/lab/2012/github-chinese-develope/

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

传统作法肯定会产生悲剧

·HTTP 请求数量过多

·会造成页面阻塞

·档案内容未压缩

·需用全域变数沟通

·载入得考虑先后顺序

·没有清楚的架构、易陷入混乱

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

MINI

透过设定档

将多个檔案合并、最小化

的开发环境工具

http://www.flickr.com/photos/prettypony/2644225789/

https://github.com/josephj/mini

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

Mini 的设定档, 十分容易设定

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

寻找档案的路径,可以设定多个$DEV_ROOT 是 VirtualHost 的环境变量

Mini 的设定档, 十分容易设定

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

寻找档案的路径,可以设定多个$DEV_ROOT 是 VirtualHost 的环境变量

定义 demo 有哪些 CSS 与 JS 档

Mini 的设定档, 十分容易设定

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

指定 type 与 module 即可自动合并且最小化

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

指定 type 与 module 即可自动合并且最小化

/mini?module=<module>&type=<css|js>

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

指定 type 与 module 即可自动合并且最小化

/mini?module=<module>&type=<css|js>

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

没有 Mini 时的情况

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

没有 Mini 时的情况

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

透过 Mini 可以大幅减少请求数量

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

透过 Mini 可以大幅减少请求数量

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

由于 Mini 没有缓存机制、只能用在开发环境

在 build 时得预先产生合并及最小化后的档案

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

由于 Mini 没有缓存机制、只能用在开发环境

在 build 时得预先产生合并及最小化后的档案

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

由于 Mini 没有缓存机制、只能用在开发环境

在 build 时得预先产生合并及最小化后的档案

线上的 CSS/JS 在 Build 后成为单一档案

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

页层级设定模式的整体架构

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

页层级设定模式的整体架构

很直觉的载入机制,可以有效地将模块档案合并压缩

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

这是 miiiCasa 从一开始就使用的模块加载方式

网站上线后都很稳定、很满意

但随著几次的改版,我們發现了不少问题

页层级设定模式

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

改版必定伴随著模块 (功能) 的新增、修改、移除

修改 Mini 的组态设定不就好了吗?

缺点 - 维护不易

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

改版必定伴随著模块 (功能) 的新增、修改、移除

修改 Mini 的组态设定不就好了吗?

缺点 - 维护不易

改版到新版后,有 3 个页面模块需要移除(基本就有 9 个档案需移除)

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

但模块依赖关系是非常复杂的!

http://www.flickr.com/photos/kalavinka/4617897952/

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

但模块依赖关系是非常复杂的!

http://www.flickr.com/photos/kalavinka/4617897952/

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

但模块依赖关系是非常复杂的!

页面模块 JavaScript

http://www.flickr.com/photos/kalavinka/4617897952/

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

但模块依赖关系是非常复杂的!

功能模块 JavaScript

页面模块 JavaScript

http://www.flickr.com/photos/kalavinka/4617897952/

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

但模块依赖关系是非常复杂的!YUI CSS

页面模块 CSS

功能模块 JavaScript

页面模块 JavaScript

http://www.flickr.com/photos/kalavinka/4617897952/

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

但模块依赖关系是非常复杂的!YUI CSS

页面模块 CSS

功能模块 JavaScript

页面模块 JavaScript

想要移除一个页面模块哪些功能模块也需要一起移除呢?

http://www.flickr.com/photos/kalavinka/4617897952/

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

解决依赖问题,最近很火热的 AMD 架构

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

6006

// 定义⼀一个 AMD 模块define(“editor”, [“handlebars”], function () {    function Editor { /* Constructor */ }    return Editor;},);

解决依赖问题,最近很火热的 AMD 架构

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

6006

// 定义⼀一个 AMD 模块define(“editor”, [“handlebars”], function () {    function Editor { /* Constructor */ }    return Editor;},);

解决依赖问题,最近很火热的 AMD 架构

第二个参数可以定义此模块需要哪些模块

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

6006

6006

// 定义⼀一个 AMD 模块define(“editor”, [“handlebars”], function () {    function Editor { /* Constructor */ }    return Editor;},);

解决依赖问题,最近很火热的 AMD 架构

// 使用⼀一个 AMD 模块require(["editor"], function (Editor) {    new Editor();});

第二个参数可以定义此模块需要哪些模块

在使用时以动态载入方式将相关模块档案一并载入

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

缺点 - Build 耗时过久我们共有这么多的页面需预先 Build:

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

缺点 - Build 耗时过久我们共有这么多的页面需预先 Build:

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

miiiCasa Build 流程中得为所有页面建置静态档此单项作业得耗时 2 分半!

缺点 - Build 耗时过久我们共有这么多的页面需预先 Build:

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

miiiCasa Build 流程中得为所有页面建置静态档此单项作业得耗时 2 分半!

但是持续整合的标准是完整 Build 不应超过 10 分钟

缺点 - Build 耗时过久我们共有这么多的页面需预先 Build:

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

缺点 - 线上除虫困难

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

缺点 - 线上除虫困难

即使经过 Beautifier 仍不易修改、还是得 Build、对要求敏捷开发就差了些

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

每页的 JS 与 CSS 档案都是完全不重复的也因此没有办法做到跨页间的缓存

缺点 - 缓存效率差

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

miii_index_my_contact_18fa331dfbf2bd392660925ba8f41239.js

miii_index_my_contact_34945d9e0efb63c7dc62dcbbc3442a60.css

两页有许多共用的页面模块、却无缓存的好处

miii_index_my_device_704b3ae3682d178a94465c066b0f6d42.js

miii_index_my_device_623f7e30575a7180ddeb11fd748aed31.css

缺点 - 缓存效率差

后来我们为了缓存、抽离出一些共用 Mini 模块

但这样做反而让设定更难易维护

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

模块层级设定模式真正的模块导向开发!

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

我心目中的乌托邦!让模块化开发不需要再有烦恼页面配置!

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

我心目中的乌托邦!让模块化开发不需要再有烦恼页面配置!

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

我心目中的乌托邦!

开发者专注于单一模块的开发设定此模块需要哪些依赖模块

让模块化开发不需要再有烦恼页面配置!

模块架构

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

我心目中的乌托邦!

Loader 计算出页面有哪些模块需载入

开发者专注于单一模块的开发设定此模块需要哪些依赖模块

让模块化开发不需要再有烦恼页面配置!

模块架构

模块 Loader

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

我心目中的乌托邦!

Loader 计算出页面有哪些模块需载入

开发者专注于单一模块的开发设定此模块需要哪些依赖模块

让模块化开发不需要再有烦恼页面配置!

模块架构

模块 Loader

远端模块载入机制服务器与浏览器端交互配合自动以效能最佳化方式载入远端模块

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

RequireJS 是目前最牛逼的 AMD 实作

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

RequireJS 是目前最牛逼的 AMD 实作

可以自动一个一个载入依赖的模块或发布前透过 r.js 做合并及最小化

// AMD Moduledefine(“editor”, [‘a’,’b’,’c’], function () {    function Editor { /* Constructor */ }    return Editor;});require(["editor"], function (Editor) {    new Editor();});

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

RequireJS 是目前最牛逼的 AMD 实作

可以自动一个一个载入依赖的模块或发布前透过 r.js 做合并及最小化

// AMD Moduledefine(“editor”, [‘a’,’b’,’c’], function () {    function Editor { /* Constructor */ }    return Editor;});require(["editor"], function (Editor) {    new Editor();});

合并与最小化仍然会有线上除错困难与

Build 时间过久的两个问题、

甚至模块一多对开发速度也会造成冲击

RequireJS 的架构因此不太符合我的需求

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

国内较少人使用的 YUI 函式库

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

国内较少人使用的 YUI 函式库

早在三年前、2009/6 月就提出的模块架构

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

国内较少人使用的 YUI 函式库

早在三年前、2009/6 月就提出的模块架构

// AMD Moduledefine(‘editor’, [‘a’,’b’,’c’], function () {    function Editor { /* Constructor */ }    return Editor;});

require(["editor"], function (Editor) {    new Editor();});

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

国内较少人使用的 YUI 函式库

早在三年前、2009/6 月就提出的模块架构

跟去年才有的 AMD、所要解决模块依赖性的思路是一致的

// AMD Moduledefine(‘editor’, [‘a’,’b’,’c’], function () {    function Editor { /* Constructor */ }    return Editor;});

require(["editor"], function (Editor) {    new Editor();});

// YUI ModuleYUI.add("editor", function () {    function Editor { /* Constructor */ }    Y.Editor = Editor;    }, “VERSION”, {requires:[‘a’,’b’,’c’]});

YUI.use("editor", function (Y) {    new Y.Editor();});

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

以 YUI DataTable 为范例

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

以 YUI DataTable 为范例

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

以 YUI DataTable 为范例

不 Reload 的行为很多:换页、排序、直接编辑。也可以接受各类资料来源,是很复杂的模组

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

只要几行代码就可以载入所需模块

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

只要几行代码就可以载入所需模块

<script src="http://yui.yahooapis.com/3.5.0/build/yui/yui-min.js"></script>

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

只要几行代码就可以载入所需模块

<script src="http://yui.yahooapis.com/3.5.0/build/yui/yui-min.js"></script>

<script>

    

</script>

YUI().use('datatable', function (Y) {

    

});

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

只要几行代码就可以载入所需模块

<script src="http://yui.yahooapis.com/3.5.0/build/yui/yui-min.js"></script>

<script>

    

</script>

YUI().use('datatable', function (Y) {

    

});

能想像 6 行代码背后,做了多少事情吗?

alert(Y.DataTable);

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

yui (Seed)

计算所需模块的流程

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

yui (Seed)

计算所需模块的流程

YUI().use('datatable')

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

yui (Seed)

widget

datatable-core

base-build

datatable-head datatable-body

计算所需模块的流程

YUI().use('datatable')

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

escape

yui (Seed)

widget

datatable-core

base-build

datatable-head datatable-body

model-list

node-event-delegate

base-base

attribute

event-focus

base-plugin-hostnode-base node-style

classnamemanager

view

计算所需模块的流程

YUI().use('datatable')

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

escape

yui (Seed)

widget

datatable-core

base-build

datatable-head datatable-body

model-list

node-event-delegate

base-base

attribute

event-focus

base-plugin-hostnode-base node-style

classnamemanager

view

yui-base

event-delegate

pluginhost event-synthetic attribute-core attribute-events

attribute-extras array-extras array-invoke

arraylist

json-parsemodel

计算所需模块的流程

YUI().use('datatable')

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

escape

yui (Seed)

widget

datatable-core

base-build

datatable-head datatable-body

model-list

node-event-delegate

base-base

attribute

event-focus

base-plugin-hostnode-base node-style

classnamemanager

view

yui-base

event-delegate

pluginhost event-synthetic attribute-core attribute-events

attribute-extras array-extras array-invoke

arraylist

json-parsemodel

计算所需模块的流程

YUI().use('datatable')

实际上 datatable 共有 64 個模块档需载入一个一个载入会很操效能YUI 的处理方式为何?

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

强大的压缩机 Combo

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

强大的压缩机 Combo

雅虎的 Combo 机制

直接以 GET 参数将不同模块档案串连并最小化

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

强大的压缩机 Combo

雅虎的 Combo 机制

直接以 GET 参数将不同模块档案串连并最小化

http://yui.yahooapis.com/combo? <模块 1 的对应路径>&

<模块 2 的对应路径>&

<模块 3 的对应路径>& ...

<模块 n 的对应路径>

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

并行非堵塞加载YUI().use('datatable')

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

YUI 种子档案

并行非堵塞加载YUI().use('datatable')

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

YUI 种子档案

载入相关 CSS

并行非堵塞加载YUI().use('datatable')

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

将所需 JavaScript 模块分散请求、并行下载

YUI 种子档案

载入相关 CSS

并行非堵塞加载YUI().use('datatable')

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

将所需 JavaScript 模块分散请求、并行下载

YUI 种子档案

载入相关 CSS

并行非堵塞加载

分散与 Combo 逻辑考虑了:「模块先后顺序」、「模块数量」、「浏览器同时请求数量」、「浏览器 GET 长度限制」,非常的自动化。自己要做这样的机制非常不易。

YUI().use('datatable')

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

YUI().use('datatable')

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

从种子变成大树仅花了 323ms

323ms

YUI().use('datatable')

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

从种子变成大树仅花了 323ms

323ms

不了解内情的人会说 YUI 很肥很庞大实际上它只载入需要的模块、其他函式库沒有這樣的效率

YUI().use('datatable')

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

从种子变成大树仅花了 323ms

323ms

不了解内情的人会说 YUI 很肥很庞大实际上它只载入需要的模块、其他函式库沒有這樣的效率

YUI().use('datatable')

例如:使用 jQuery 真的每页都用的到 ajax 这个函式吗?

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

John ResigThe creator of jQuery

http://www.quora.com/How-could-YUI3-improve-its-image-compared-to-jQuery-MooTools-etc

YUI 载入方式实在太 Sexy 了、应被大力推广!

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

John ResigThe creator of jQuery

YUI().use() + pulling code off of Yahoo's CDN is damn sexy and should be promoted *VERY* heavily.

http://www.quora.com/How-could-YUI3-improve-its-image-compared-to-jQuery-MooTools-etc

YUI 载入方式实在太 Sexy 了、应被大力推广!

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

有模块架构、有模块 Loader、配合最佳化的远端模块载入机制!

还等什么?快到用在网站页面模块的载入机制上!

YUI 的架构正是我所期盼的

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

问题:寻找 Combo 机制的替代品

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

问题:寻找 Combo 机制的替代品

雅虎的 Combo 仅供内部使用、还好有人写了替代品!我选择的是 Minify 这个工具,一样会帮我做伺服器端的缓存、合并与档案最小化

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

问题:寻找 Combo 机制的替代品

雅虎的 Combo 仅供内部使用、还好有人写了替代品!

http://code.google.com/p/minify/

Minify (PHP5)

https://github.com/mrclay/minify

我选择的是 Minify 这个工具,一样会帮我做伺服器端的缓存、合并与档案最小化

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

问题:寻找 Combo 机制的替代品

雅虎的 Combo 仅供内部使用、还好有人写了替代品!

http://code.google.com/p/minify/

Minify (PHP5)

https://github.com/mrclay/minify

http://<your host>/minify?f= <模块 1 的对应路径>,

<模块 2 的对应路径>, ...

<模块 n 的对应路径>

我选择的是 Minify 这个工具,一样会帮我做伺服器端的缓存、合并与档案最小化

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

困难二:YUI 自订模块组态设定复杂

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

困难二:YUI 自订模块组态设定复杂

非 YUI 本身的模块得另外定义,但这样不好维护

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

困难二: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");

非 YUI 本身的模块得另外定义,但这样不好维护

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

困难三:CSS 不适用于动态加载

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

困难三:CSS 不适用于动态加载

YUI 与 RequireJS 都可以加载 CSS、但都只能采用动态加载

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

困难三:CSS 不适用于动态加载

CSS 须在 HTML 显示前就准备好,不然浏览器须一直重新绘制,对网站效能会是很大的冲击

YUI 与 RequireJS 都可以加载 CSS、但都只能采用动态加载

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

困难三:CSS 不适用于动态加载

CSS 须在 HTML 显示前就准备好,不然浏览器须一直重新绘制,对网站效能会是很大的冲击

<link rel="stylesheet" href="page.css" media="all">

YUI 与 RequireJS 都可以加载 CSS、但都只能采用动态加载

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

YUI 解决了大部分的需求剩下的桥梁得自己建设!

http://www.flickr.com/photos/defenceimages/6771187177/

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

https://github.com/josephj/static-loader

一并解决 YUI 组态的复杂度与让 CSS 传统加载

YUI 解决了大部分的需求剩下的桥梁得自己建设!

http://www.flickr.com/photos/defenceimages/6771187177/

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

两岸三地的开发者这回我们要加上模块依赖关系!

http://josephj.com/lab/2012/github-chinese-develope/

资讯模块 列表模块_info.php_info.css_info.js

_list.php_list.css_list.js

条件过滤模块 _filter.php _filter.css _filter.js

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

两岸三地的开发者这回我们要加上模块依赖关系!

http://josephj.com/lab/2012/github-chinese-develope/

资讯模块 列表模块_info.php_info.css_info.js

_list.php_list.css_list.js

条件过滤模块 _filter.php _filter.css _filter.js

module,cookie

•module

• node-event-delegate• node-style

• node-screen • cache

• jsonp

• handlebars• event-resize

•cookie

•module

• node-base• handlebars

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

每个模块的组态设定不再維護類似 Mini 的頁面設定

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

每个模块的组态设定不再維護類似 Mini 的頁面設定

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

每个模块的组态设定

模块定义自身 JS 与 CSS 位置及依赖关系

不再維護類似 Mini 的頁面設定

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

指定此页面有哪些页面模块很直觉的指定方式

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

指定此页面有哪些页面模块很直觉的指定方式

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

指定此页面有哪些页面模块

不需知道背後的依賴模塊!只要指定页面模块移除也不需要担心影响别的模块

很直觉的指定方式

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

轻易将所有需要的设定与标签输出复杂的事情应该交给程式来做啊!

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

轻易将所有需要的设定与标签输出复杂的事情应该交给程式来做啊!

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

轻易将所有需要的设定与标签输出复杂的事情应该交给程式来做啊!

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

加载的方式十分优异

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

加载的方式十分优异

以传统方式加载种子与页面 CSS

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

加载的方式十分优异

分散並發的 JS 请求是自动计算依赖关系而生成

以传统方式加载种子与页面 CSS

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

未来开发可以完全专注在模块上

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

未来开发可以完全专注在模块上A. 通知讯息模块 (_notification)

模块开发者 A

模块名称 welcome/_notification

CSS 档案 welcome/_notification.css

JS 档案 welcome/_notification.js

相依模块 scroll-pagination, node-event-delegate, viewer

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

未来开发可以完全专注在模块上A. 通知讯息模块 (_notification)

模块开发者 A

B. 页首模块 (_masthead)

模块开发者 B

模块名称 welcome/_notification

CSS 档案 welcome/_notification.css

JS 档案 welcome/_notification.js

相依模块 scroll-pagination, node-event-delegate, viewer

模块名称 common/_masthead

CSS 档案 common/_masthead.css

JS 档案 common/_masthead.js

所需模块 panel, device-navigation

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

未来开发可以完全专注在模块上A. 通知讯息模块 (_notification)

模块开发者 A

B. 页首模块 (_masthead)

模块开发者 B

C. 侧边栏模块 (_sidebar)

模块开发者 C

模块名称 welcome/_notification

CSS 档案 welcome/_notification.css

JS 档案 welcome/_notification.js

相依模块 scroll-pagination, node-event-delegate, viewer

模块名称 common/_masthead

CSS 档案 common/_masthead.css

JS 档案 common/_masthead.js

所需模块 panel, device-navigation

模块名称 welcome/_sidebar

CSS 档案 welcome/_sidebar.css

JS 档案 無

所需模块 無

<?php ?>

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

最后再 Controller 指定页面模块即可

登入后首页 (welcome.php)页面开发者

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

最后再 Controller 指定页面模块即可

登入后首页 (welcome.php)页面开发者

此页面有以下模块:

·•welcome/_notification

·•charming/_masthead

·•common/_sidebar

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

回顧页层级设定所遭遇的困难

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

回顧页层级设定所遭遇的困难

· Build 效率问题不再 Build,由 Minify 在线上自动合并、压缩、版本控管。

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

回顧页层级设定所遭遇的困难

· Build 效率问题不再 Build,由 Minify 在线上自动合并、压缩、版本控管。

·线上除错问题原始档案皆存在,可以直接修正问题,只要把 Minify 对应的缓存砍掉即可

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

回顧页层级设定所遭遇的困难

· Build 效率问题不再 Build,由 Minify 在线上自动合并、压缩、版本控管。

·线上除错问题原始档案皆存在,可以直接修正问题,只要把 Minify 对应的缓存砍掉即可

·维护性问题開發者只定义自身模块的相依性、整页所需模塊由 YUI Loader 計算後自動載入,管理容易许多。

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

回顧页层级设定所遭遇的困难

· Build 效率问题不再 Build,由 Minify 在线上自动合并、压缩、版本控管。

·线上除错问题原始档案皆存在,可以直接修正问题,只要把 Minify 对应的缓存砍掉即可

·维护性问题開發者只定义自身模块的相依性、整页所需模塊由 YUI Loader 計算後自動載入,管理容易许多。

·共用的缓存问题除了全域共用采用 Minify 中的 groupConfig,其馀不处理、避免维护问题

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

结语

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

页层级的设置可想成「中央集权」设置容易。初期一目了然,但规模变大就管理不易。

结语

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

页层级的设置可想成「中央集权」设置容易。初期一目了然,但规模变大就管理不易。

模块层级設定则是「地方自治」设置较复杂、对长期维护较有效率。

配合相依性计算、自动合并、非同步下载等机制让页面模块真的做到随插即用

结语

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

结语

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

BigPipe 是很多网站想实作的目标

但首先你得「建立模块相依性」、「采用页面模块开发模式」

先建立模块导向开发模式才可能有实作的机会

鼓励较具规模的网站开始往这方向移动

结语

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

相关连结

·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:[email protected]

今天看到的所有程式码或工具都是可分享的!

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

Questions?

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

miiiCasa家庭雲、建立家中的 SNS!

在北京工作的⼀一家人

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

miiiCasa家庭雲、建立家中的 SNS!

在北京工作的⼀一家人

在老家重慶的奶奶

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

miiiCasa家庭雲、建立家中的 SNS!

在北京工作的⼀一家人

在老家重慶的奶奶

位於家中、可存放照片的分享器

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

miiiCasa家庭雲、建立家中的 SNS!

在北京工作的⼀一家人

在老家重慶的奶奶

位於家中、可存放照片的分享器

互连网

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

miiiCasa家庭雲、建立家中的 SNS!

在北京工作的⼀一家人

在老家重慶的奶奶

想看孫女只要换个频道就可以了

位於家中、可存放照片的分享器

互连网

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