日期:2013-09-21  浏览次数:20663 次

就要开始新的项目了,全站的前端架构也要开始构思,得益于之前做雅虎关系时的一些或成功或失败的实践总结,还是该当从架构的层面着手,去处理一些前端团队开发的问题。如今市面上有着各种各样的js库和框架,但库和框架还是有很大区别的,首先,“库”是widget的一个集合,特点是上手容易使用简便,参照例子只大概只需求援用一个script标签到页面中,再加上一些简单的类似a.start(config)的启动代码就可以了,而框架则是网站的树状结构的笼统,包括模块关系,功用之间的依赖,入口的先后顺序,以及功用的hack等等,侥幸的是阿里还是很明智的选择了yui作为其前端架构的底层,只是由于yui2强大丰富的widget库,使得多数人认为yui2更是一个库而非框架,而yui2的yuiloader也仅仅是一个可选的模块,这样就愈加淡化了yui2在框架层面灵活强大的表现力,团体认为如果网站没有以yuiloader搭建起来的模块树做支撑,yui2的作用无疑是一把牛刀只用作杀鸡而已。在yui3中,这种情况有了基本改变,框架层面的模块化代替了简单的库,这对于团队开发的大型网站是很有启发的。

当然,在做前端开发的时候,使用loader必然要多写几行代码,多几次封装,又麻烦又不方便,这样做到底好在什么地方呢。这个话题大概说来话长,这里只从网站规模和项目特点的方面来作简单说明:

像taobao这种大型的网站,前端开发占有不小的比重,这类网站普通会按照大类划分成不同的产品,每个产品相当于一个独立完整的网站,只要全体款式风格和组件会和主战保持分歧。

那么从web前端角度讲,这类网站大致包含四部分内容:
1),网站下辖站点所需的全局变量和函数,包括所有子站共通的部分
2),子站外框(公共头尾)
3),网页主体内容
4),组件

依据三者的特点,各自的重用情况为:
1),全站的全局变量和函数:几乎每个页面都要用到
2),子站外框:几乎每个子站的网页都保持分歧
3),网页的主体内容,不可重用
4),组件:重用率高,但是被有选择的调用,只在必要的时候才会援用组件

从需求的角度上讲,这类网站的特点是更新频繁,从工程的角度讲,代码的维护成本大于甚至远远大于代码开发成本。也就是说项目随着时间的推移,修正功用的项目数量要远远大于新功用的开发,到项目的中后期,工程师的大部分时间不是写新代码,而是花大量的经历去读旧代码,或者进行功用优化,或者针对新需求进行改进。不管是功用改进还是需求改进,都将添加代码的熵,代码污染也会越来越严重,维护成本也会急剧变大,这让项目后期开发工程师苦不堪言,有一部分缘由是项目前期文档不全,缺少写代码的必要的约束和商定,再者是注释不够及时和规范,导致代码可读性差,三是工程师水平参差不齐,有些人在修正代码过程中会无认识的破坏原有代码的结构,四是时间压力导致代码质量下降,五是框架结构的不合理。

完善文档和规范、添加新人培训力度可以以处理一部分问题,但这往往和制度和执行力度有关。从项目生命周期来看,项目分为叠代和快速开发,快速开发是开发时间短,不需求和其他项目并行,及时开发及时测试及时打包上线,和其他项目发生冲突的可能性很小,简单迭代的开发模式是基于分支和主干的多线程的并行开发。在此基础上的前端开发也是保持和后段开发同步的迭代。迭代的优点是项目并行和减少冲突的发生。从后端开发的角度看,经常多人开发同一个页面,只是每个工程师担任的模块不同而已,普通情况下页面中只要include的入口,然后调用各自工程师的代码,这样在页面中的代码污染就比较低,但是随着页面复杂度的添加,后段代码会越来越多的直接出如今页面当中,比如使用更多的echo代替模版,html代码中嵌套更多的if判断和for循环。这样会添加代码污染的程度。从前端开发来看,也会经常出现多人合作开发同一个页面,也是每人担任不同的功用模块,这里有两种情况,1是多人同时开发不同的使用模块,两者没有依赖关系,2是多人分别开发框架和使用,两者之间有依赖关系,使用依赖框架。而两者之间的耦合该当仅仅以入口调用作为接口,因此前端框架该当考虑到这种情况,即多人开发的前端功用代码该当尽可能地分离。

在js代码的写法上,自然推荐将代码都封装到页面的js文件中,在page中只留出入口。然而实际情况并非如此,在缺少框架约束的情况下,多数人不会选择去在读懂之前的烂代码的基础上再添加本人的代码,通常会直接用最简单粗暴的用script标签引一个js,紧跟着开一段script代码块写启动入口,甚至于连script标签都烂的写,直接在原先代码块中直接开辟一段区域本人加代码。这种做法该当如何看待呢?从库的角度讲,库中给了很多模块的实例,使用模块的方式大都也是手写一个script标签引一个js文件,然后再页面中添加启动入口。那么当多人开发同一个页面中的不同功用的时候就会这样做:

首先,a在页面中实现了一个功用,大致是这个样子:
<script src="base.js" /><!--库的种子-->
<script src="a.js" />
<script>
a.start();
</script>

b也实现了另外一个功用,大致是这个样子:
<script src="base.js" /><!--库的种子-->
<script src="b.js" />
<script>
b.start();
</script>

b在coding的时候多数情况不会去review页面代码,或者说review了页面的烂代码也看不懂,再或者说两团体并行开发,并不知晓对方的实现。这样就会导致base.js的援用反复。

另外一种情况是,如果一个例子比较复杂,需求援用多个js文件,比如:
<script src="base.js" /><!--库的种子-->
<script src="a.js" />
<script src="b.js" />
<script>
m.start();
</script>

那么a.js和b.js的援用顺序则需求特别留意,但在实际开发中,并不能保证每团体都能细心的将js文件的顺序排好,如果排乱了顺序则需求比较多的调试成本。所以由此看出,纯粹基于“库”模式的开发会带来很多隐患,这里只提到了开发过程中常遇到的问题,另外,这种手写js标签援用js文件的方式也是缺乏语义并牺牲了功用(每个script src占用一个http请求?),同时,inline script block散步在页面的各个角落,虽然每个script block都被匿名函数闭包起来,开发速度很快,但这种代码毫无结构性可言,对于其他人也是晦涩难懂,等到项目中后期的维护成本会很高,所以说换作谁都不情愿去接手维护一个如此coding的项目。因此,可以认为这种coding方式所导致的代码污染会大大降低生产率(这里的生产率包括开发和维护两部分)和页面功用。

而yui3强制使用Ylaoder,从结构上一定程度的保证代码质量和可读性。按照yui3的思路,项目的前期该当花大精力去做模块的依赖,在此基础上开发出丰富的widget,使用过程中指需求load模块名字,而不必去关系模块需求依赖那些js,以及这些js的先后顺序是什么。另外,通过简单hack,loader可以将yui3以及所有项目js都combo在一同(taobao assetcdn如今不提供这种功用,不过很快就会有了),在多的模块都合并到一个js http请求中,外加一个种子,一个页面的js http请求顶多只要两个。

那么能否可以说,象taobao这种复杂多变(需求变更频繁)的大网站就可以用yui3来架构,以避免深度的代码污染了呢?非也,yui3在设计上并不能满足类似taobao的这种门户。上文提到了网站的四个组成部分,全局、外框、主内容区和组件,他们之间的关系该当是什么样的呢?显然,页面rander的时候,该当首先加载全局变量