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

Post on 15-Jan-2015

3.451 Views

Category:

Technology

6 Downloads

Preview:

Click to see full reader

DESCRIPTION

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

TRANSCRIPT

模块加载策略

讲者 - 蒋定宇 / josephj

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

Module Loader Strategy

关于我 - 蒋定宇 (josephj)

关于我 - 蒋定宇 跑步环岛

·共 27 天·约 900 多公里

2008 年 5 月份

(josephj)

关于我 - 蒋定宇

雅虎奇摩

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

跑步环岛

·共 27 天·约 900 多公里

2008 年 5 月份

2005.10 - 2009.8

(josephj)

关于我 - 蒋定宇

雅虎奇摩

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

miiiCasa 云永科技

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

跑步环岛

·共 27 天·约 900 多公里

2008 年 5 月份

2005.10 - 2009.8

2009.9 至今

(josephj)

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

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

担任讲师感谢裕波!

百度参访

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

担任讲师感谢裕波!

百度参访

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

北京 WebRebuild 演講,收獲滿檔!

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

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

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

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

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

NASA 美国太空总署太空站

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

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

NASA 美国太空总署太空站

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

模块化开发是必然趋势:

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

GitHub

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

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

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

网页中的模块又是什么?

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

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

网页中的模块又是什么?

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

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

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

网页中的模块又是什么?

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

主题:模块加载策略

主题:模块加载策略

·传统 模式

主题:模块加载策略

·传统 模式

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

主题:模块加载策略

·传统 模式

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

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

传统模式

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

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

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

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

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

两岸三地的 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

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

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

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

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

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

页面模块的 HTML 结构

<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 结构

<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 代表一个模块

不能重复

<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 代表模块的标

头、内容、标尾结构

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

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

<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 的縮寫

<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 的縮寫

老道所提的 JavaScript 模块模式

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

}();

老道所提的 JavaScript 模块模式

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

}();

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

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

    publicFn = function () {};

老道所提的 JavaScript 模块模式

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

}();

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

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

    publicFn = function () {};

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

老道所提的 JavaScript 模块模式

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

}();

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

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

    publicFn = function () {};

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

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

Nicholas ZakasFormer Principal Front End Engineer, Yahoo!

Zakas 的 Scalable JavaScript 模块

观察者模式:

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

https://github.com/miiicasa/module

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

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

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

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

天哪!我该如何处理

这么多模块档案呢?

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

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

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

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

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

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

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

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

两岸三地的开发者

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

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

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

两岸三地的开发者

列表模块_list.php_list.css_list.js

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

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

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

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

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

传统作法肯定会产生悲剧

·HTTP 请求数量过多

·会造成页面阻塞

·档案内容未压缩

·需用全域变数沟通

·载入得考虑先后顺序

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

MINI

透过设定档

将多个檔案合并、最小化

的开发环境工具

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

https://github.com/josephj/mini

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

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

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

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

定义 demo 有哪些 CSS 与 JS 档

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

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

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

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

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

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

没有 Mini 时的情况

没有 Mini 时的情况

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

页层级设定模式

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

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

缺点 - 维护不易

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

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

缺点 - 维护不易

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

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

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

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

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

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

页面模块 JavaScript

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

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

功能模块 JavaScript

页面模块 JavaScript

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

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

页面模块 CSS

功能模块 JavaScript

页面模块 JavaScript

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

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

页面模块 CSS

功能模块 JavaScript

页面模块 JavaScript

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

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

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

6006

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

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

6006

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

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

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

6006

6006

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

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

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

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

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

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

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

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

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

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

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

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

缺点 - 线上除虫困难

缺点 - 线上除虫困难

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

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

缺点 - 缓存效率差

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 模块

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

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

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

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

我心目中的乌托邦!

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

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

模块架构

我心目中的乌托邦!

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

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

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

模块架构

模块 Loader

我心目中的乌托邦!

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

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

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

模块架构

模块 Loader

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

RequireJS 是目前最牛逼的 AMD 实作

RequireJS 是目前最牛逼的 AMD 实作

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

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

RequireJS 是目前最牛逼的 AMD 实作

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

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

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

Build 时间过久的两个问题、

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

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

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

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

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

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

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

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

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

国内较少人使用的 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();});

以 YUI DataTable 为范例

以 YUI DataTable 为范例

以 YUI DataTable 为范例

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

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

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

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

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

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

<script>

    

</script>

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

    

});

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

<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);

yui (Seed)

计算所需模块的流程

yui (Seed)

计算所需模块的流程

YUI().use('datatable')

yui (Seed)

widget

datatable-core

base-build

datatable-head datatable-body

计算所需模块的流程

YUI().use('datatable')

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')

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')

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 的处理方式为何?

强大的压缩机 Combo

强大的压缩机 Combo

雅虎的 Combo 机制

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

强大的压缩机 Combo

雅虎的 Combo 机制

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

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

<模块 2 的对应路径>&

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

<模块 n 的对应路径>

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

YUI 种子档案

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

YUI 种子档案

载入相关 CSS

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

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

YUI 种子档案

载入相关 CSS

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

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

YUI 种子档案

载入相关 CSS

并行非堵塞加载

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

YUI().use('datatable')

YUI().use('datatable')

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

323ms

YUI().use('datatable')

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

323ms

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

YUI().use('datatable')

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

323ms

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

YUI().use('datatable')

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

John ResigThe creator of jQuery

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

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

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 了、应被大力推广!

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

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

YUI 的架构正是我所期盼的

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

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

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

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

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

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

Minify (PHP5)

https://github.com/mrclay/minify

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

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

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

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

Minify (PHP5)

https://github.com/mrclay/minify

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

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

<模块 n 的对应路径>

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

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

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

非 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");

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

每个模块的组态设定

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

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

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

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

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

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

很直觉的指定方式

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

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

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

加载的方式十分优异

加载的方式十分优异

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

加载的方式十分优异

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

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

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

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

模块开发者 A

模块名称 welcome/_notification

CSS 档案 welcome/_notification.css

JS 档案 welcome/_notification.js

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

未来开发可以完全专注在模块上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

未来开发可以完全专注在模块上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 ?>

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

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

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

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

此页面有以下模块:

·•welcome/_notification

·•charming/_masthead

·•common/_sidebar

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

结语

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

结语

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

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

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

结语

结语

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

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

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

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

结语

相关连结

·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

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

Questions?

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

在北京工作的⼀一家人

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

在北京工作的⼀一家人

在老家重慶的奶奶

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

在北京工作的⼀一家人

在老家重慶的奶奶

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

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

在北京工作的⼀一家人

在老家重慶的奶奶

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

互连网

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

在北京工作的⼀一家人

在老家重慶的奶奶

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

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

互连网

top related