Skip to content

Commit

Permalink
[UPD] update some files.
Browse files Browse the repository at this point in the history
  • Loading branch information
fouber committed Aug 26, 2015
1 parent 329a4bf commit 42f110d
Showing 1 changed file with 17 additions and 19 deletions.
36 changes: 17 additions & 19 deletions 201508/01.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,14 @@

## 前端工程的三个阶段

为了提升前端的开发效率和运行性能,前端团队的工程建设大致会经历三个阶段:
现在的前端开发倒也并非一无所有,回顾一下曾经经历过或听闻过的项目,为了提升其前端开发效率和运行性能,前端团队的工程建设大致会经历三个阶段:

### 第一阶段:库/框架选型

![](assets/libs.png)

前端工程的第一项任务就是根据项目特征进行技术选型,基础库或框架可以为项目节省许多工程量这点毋庸置疑。

技术选型一般不包括封装好的可复用组件库选型,因为前端项目通常都具有极强的个性化定制需求以及代码最小化精简需求,这两项要求对组件复用性带来了极大的挑战,所以除了某些类型的前端项目之外——比如xx后台管理系统——前端组件的复用性现阶段来说基本是一个伪命题。

### 第二阶段:简单构建优化

![](assets/tools.png)
Expand All @@ -46,7 +44,7 @@

分而治之是软件工程中的重要思想,是复杂系统开发和维护的基石,这点放在前端开发中同样适用。在解决了基本开发效率运行效率问题之后,前端团队开始思考维护效率,模块化是目前前端最好的分治手段。

> 很多人觉得模块化开发的工程意义是复用,我不太认可这种看法,在我看来,模块化开发的最大价值其实是分治,是分治,分治!(重说三)。
> 很多人觉得模块化开发的工程意义是复用,我不太认可这种看法,在我看来,模块化开发的最大价值应该是分治,是分治,分治!(重说三)。
业界目前常用的JS模块化开发方式就是基于requirejs/seajs的模块化方案,CSS模块化开发基本是在less/scss/sass/stylus等预处理器的import/mixin特性支持下实现的。

Expand Down Expand Up @@ -78,17 +76,17 @@

前端历来以“简单”著称,在前端开发者群体中,小而美的价值观占据着主要的话语权,甚至成为了某种信仰,想与其他人交流一下工程方面的心得,得到的回应往往都是两个字:太重。

No,No,No,工程方案也可以小而美!它的小而美是指“规则”找到问题的根源,用最少最简单明了的规则制定出最容易遵守最容易理解的开发规范或工具,以提升开发效率和工程质量,这同样是小而美的典范!
No,No,No,工程方案也可以小而美!只不过它的小而美不是指代码量,而是指“规则”找到问题的根源,用最少最简单明了的规则制定出最容易遵守最容易理解的开发规范或工具,以提升开发效率和工程质量,这同样是小而美的典范!

2011年我有幸参与到 [FIS](http://fis.baidu.com) 项目中,与百度众多大中型项目的前端研发团队共同合作,不断探索实践前端开发的工程化解决方案,13年离开百度去往UC,面对完全不同的产品形态,不同的业务场景,不同的适配终端,甚至不同的网络环境,过往的方法论仍然能够快速落地,为多个团队的不同业务场景量身定制出合理的前端解决方案。

这些经历让我明悟了一个道理:

> 进入第四阶段,我们只需做好两件事就能大幅提升前端开发效率,并且兼顾运行性能
> 进入第四阶段,我们只需做好两件事就能大幅提升前端开发效率,并且兼顾运行性能它们就是——组件化开发与资源管理
### 第一件事:组件化开发

分治的确是非常重要的工程优化手段。在我看来,前端作为一种GUI软件,对于UI组件的分治开发维护有着最为迫切的需求
分治的确是非常重要的工程优化手段。在我看来,前端作为一种GUI软件,光有JS/CSS的模块化还不够,对于UI组件的分治开发维护也有着同样迫切的需求

![](assets/components.png)

Expand All @@ -102,13 +100,13 @@ No,No,No,工程方案也可以小而美!它的小而美是指“规则

其中第二项描述的就近维护原则,是我觉得最具工程价值的地方,它为前端开发提供了很好的分治策略,每个开发者都将清楚的知道,自己所开发维护的功能单元,其代码必然存在于对应的组件目录中,在那个目录下能找到有关这个功能单元的所有内部逻辑,样式也好,JS也好,页面结构也好,都在那里。

组件化开发具有较高的通用性,无论是前端渲染的单页面应用,还是后端模板渲染的多页面应用,组件的HTML内容,根据业务技术选型的不同,可以是静态的HTML文件,可以是前端模板,也可以是后端模板:
组件化开发具有较高的通用性,无论是前端渲染的单页面应用,还是后端模板渲染的多页面应用,组件的HTML部分根据业务技术选型的不同,可以是静态的HTML文件,可以是前端模板,也可以是后端模板:

![](assets/templates.png)

> 不同的技术选型决定了不同的组件封装和调用策略,后续再展开讨论
> 不同的技术选型决定了不同的组件封装和调用策略。
基于这样的工程理念,我们很容易将系统以独立的组件为单元进行分工
基于这样的工程理念,我们很容易将系统以独立的组件为单元进行分工划分

![](assets/split.png)

Expand Down Expand Up @@ -143,15 +141,15 @@ No,No,No,工程方案也可以小而美!它的小而美是指“规则

> 吐槽:我本人非常反对某些前端团队将前端开发划分为“JS开发”和“页面重构”两种岗位,更倾向于组件粒度的开发理念,对GUI软件开发的分工规划应该以功能为单位,而不是开发语言;对开发者的技术要求也应该是掌握完整的端内技术。
### 第二件事:“智能”静态资源加载
### 第二件事:“智能”静态资源管理

上面提到的模块化/组件化开发,仅仅描述了一种开发理念,也可以认为是一种开发规范,倘若你认可这规范,对它的分治策略产生了共鸣,那我们就可以继续聊聊它的具体实现了。

很明显,模块化/组件化开发之后,我们最终要解决的,就是模块/组件加载的技术问题。前端与客户端GUI软件有一个很大的不同:

> 前端是一种程⃨序⃨资⃨源⃨部⃨署⃨在⃨远⃨程⃨,运⃨行⃨时⃨增⃨量⃨下⃨载⃨的GUI软件
前端应用没有安装过程,其所需程序资源都部署在远程服务器,用户使用浏览器访问不同的页面来加载不同的资源,随着页面访问的增加,渐进式的将整个程序下载到本地运行,由此可见,对于前端程序来说,“增量下载”是其在工程上有别于客户端GUI软件的根本原因
前端应用没有安装过程,其所需程序资源都部署在远程服务器,用户使用浏览器访问不同的页面来加载不同的资源,随着页面访问的增加,渐进式的将整个程序下载到本地运行,“增量下载”是前端在工程上有别于客户端GUI软件的根本原因

![](assets/gui.gif)

Expand All @@ -165,9 +163,9 @@ No,No,No,工程方案也可以小而美!它的小而美是指“规则

> 第四阶段前端开发最迫切需要做好的就是在基础架构中贯彻增量原则。
我相信这种贯彻不会随着时间的推移而改变,在可预见的未来,无论在HTTP1.x还是HTTP2.0时代,无论在ES5亦或者ES6/7时代,无论是AMD/CMD亦或者ES6 module时代,不管端内技术如何变迁,我们都有足够充分的理由要做好程序资源的增量加载。
相信这种贯彻不会随着时间的推移而改变,在可预见的未来,无论在HTTP1.x还是HTTP2.0时代,无论在ES5亦或者ES6/7时代,无论是AMD/CMD亦或者ES6 module时代,不管端内技术如何变迁,我们都有足够充分的理由要做好程序资源的增量加载。

正如我在前面说到的,第三阶段前端工程缺少点什么呢?我觉得是在其基础架构中缺少这样一种“智能”的资源加载方案。没有这样的方案,你很难将前端应用的规模发展到第四阶段,也很难让多方合作高效率的完成一项大型应用并保证其最终的运行性能良好。
正如前面说到的,第三阶段前端工程缺少点什么呢?我觉得是在其基础架构中缺少这样一种“智能”的资源加载方案。没有这样的方案,很难将前端应用的规模发展到第四阶段,也很难让多方合作高效率的完成一项大型应用并保证其最终的运行性能良好。

在我的印象中,Facebook是这方面探索的伟大先驱之一,早在2010年的[Velocity China大会](http://velocity.oreilly.com.cn/2010/)上,来自Facebook的[David Wei博士](http://davidwei.org/)就为业界展示了他们令人惊艳的[静态网页资源管理和优化](http://velocity.oreilly.com.cn/2010/index.php?func=session&name=%E9%9D%99%E6%80%81%E7%BD%91%E9%A1%B5%E8%B5%84%E6%BA%90%E7%9A%84%E7%AE%A1%E7%90%86%E5%92%8C%E4%BC%98%E5%8C%96)技术。

Expand All @@ -185,11 +183,11 @@ David Wei博士在当年的交流会上提到过一些关于Facebook的一些产

![](assets/velocity.png)

那段时间 [FIS](http://fis.baidu.com) 项目正好遇到瓶颈,当时的FIS就是一个用php写的task-based构建工具,在我们当时的理解中,前端构建不就是几个压缩优化校验打包任务的组合吗,写好流程调度,就可以写各种插件了,看似非常简单。但当我们支撑越来越多的业务团队,接触到各种不同的业务场景时,我们深刻的感受到task-based工具的粗糙,构建变成越来越大的黑盒,团队每天疲于根据各种业务场景编写各种打包插件,构建逻辑异常复杂,隐隐看到不可控的迹象。
那段时间 [FIS](http://fis.baidu.com) 项目正好遇到瓶颈,当初的FIS就是一个用php写的task-based构建工具,在我们当时看来,前端构建不就是几个压缩优化校验打包任务的组合吗,写好流程调度,就可以开发各种插件了,看似非常简单。但当我们支撑越来越多的业务团队,接触到各种不同的业务场景时,我们深刻的感受到task-based工具的粗糙,构建变成越来越大的黑盒,团队每天疲于根据各种业务场景编写各种打包插件,构建逻辑异常复杂,隐隐看到不可控的迹象。

我们明显的意识到把基础架构放到构建工具中实现是一件很愚蠢的事,因为构建工具有很强的黑盒效应,一旦发生问题,定位起来非常困难,而且每种业务场景都有不同的有关增量加载的优化需求,单页面/多页面/PC端/移动端/前端渲染/后端渲染/多语言/多皮肤/高级优化等等问题,总不能针对每种技术都写一份工具吧,更何况他们彼此之间还可以有多种组合情况
我们很快意识到把基础架构放到构建工具中实现是一件很愚蠢的事,因为构建工具很黑盒,一旦发生问题,定位起来非常困难,而且每种业务场景都有不同的有关增量加载的优化需求,构建工具只能静态分析来优化加载,具有很大的局限性,业务中的单页面/多页面/PC端/移动端/前端渲染/后端渲染/多语言/多皮肤/高级优化等等问题,总不能针对每种技术都写一份工具吧,更何况这些问题彼此之间还可以有多种组合情况,工具根本写不过来

Facebook的做法无疑为我们亮起了一盏明灯,不过可惜它并不开源(不是技术壁垒,而是这个系统依赖FB体系中的其他方面,开源意义不大),我们只能尝试挖掘相关信息,不过网上对它的完整介绍还是非常非常少,分析facebook的前端代码也没有太多收获。后来无意中发现了facebook使用的项目管理工具[phabricator](http://phabricator.org/)中的一个静态管理方案[Celerity](https://secure.phabricator.com/book/phabdev/article/celerity/),以及相关的[说明](https://secure.phabricator.com/book/phabflavor/article/soon_static_resources/),看它的描述很像是Facebook静态资源管理系统的一个mini版!
Facebook的做法无疑为我们亮起了一盏明灯,不过可惜它并不开源(不是技术封锁,而是这个系统依赖FB体系中的其他方面,通用性不强,开源意义不大),我们只能尝试挖掘相关信息,网上对它的完整介绍还是非常非常少,分析facebook的前端代码也没有太多收获。后来无意中发现了facebook使用的项目管理工具[phabricator](http://phabricator.org/)中的一个静态管理方案[Celerity](https://secure.phabricator.com/book/phabdev/article/celerity/),以及相关的[说明](https://secure.phabricator.com/book/phabflavor/article/soon_static_resources/),看它的描述很像是Facebook静态资源管理系统的一个mini版!

简单看过整个系统之后原理并不复杂,它是通过一个小工具扫描所有静态资源,生成一张资源表,然后有一个PHP实现的资源管理框架(Celerity)提供了资源加载接口,替代了传统的script/link等静态的资源加载标签,最终通过读取表来加载资源。

Expand Down Expand Up @@ -227,9 +225,9 @@ Facebook的做法无疑为我们亮起了一盏明灯,不过可惜它并不开
![](assets/srms.png)

这种设计很快被验证具有足够的灵活性,能够完美支撑不同团队不同技术规范下的性能优化需求,前面提到的按需加载、延迟加载、预加载、请求合并、文件指纹、CDN部署、Bigpipe、Quickling、BigRender、首屏CSS内嵌、HTTP 2.0服务端推送等等性能优化手段都可以在这种架构上实现,甚至可以根据性能日志自动进行优化(Facebook已实现)。因为有了资源表,我们可以很方便的控制资源加载,在运行时计算页面的资源使用情况,从而获得最佳加载性能。无论是前端组装HTML的单页面应用,还是后端组装HTML的多页面应用,这种方法都同样适用。
这种设计很快被验证具有足够的灵活性,能够完美支撑不同团队不同技术规范下的性能优化需求,前面提到的按需加载、延迟加载、预加载、请求合并、文件指纹、CDN部署、Bigpipe、Quickling、BigRender、首屏CSS内嵌、HTTP 2.0服务端推送等等性能优化手段都可以在这种架构上实现,甚至可以根据性能日志自动进行优化(Facebook已实现)。因为有了资源表,我们可以很方便的控制资源加载,在运行时计算页面的资源使用情况,从而获得最佳加载性能。无论是前端渲染的单页面应用,还是后端渲染的多页面应用,这种方法都同样适用。

此外,它还很巧妙的约束了构建工具的职责——只生成资源表资源表是非常通用的数据结构,无论什么业务场景,其代码最终都可以被扫描为相同结构的表数据,并标记资源间的依赖关系,而FIS团队只要根据不同的业务场景定制不同的资源加载框架就行了,从此彻底告别一个团队维护一套工具的时代!!!
此外,它还很巧妙的约束了构建工具的职责——只生成资源表资源表是非常通用的数据结构,无论什么业务场景,其代码最终都可以被扫描为相同结构的表数据,并标记资源间的依赖关系,有了表之后我们只需根据不同的业务场景定制不同的资源加载框架就行了,从此彻底告别一个团队维护一套工具的时代!!!

![](assets/srms-2.png)

Expand Down

0 comments on commit 42f110d

Please sign in to comment.