「小白DAY6」谈前端架构的设计与进化

「小白DAY6」谈前端架构的设计与进化

引言

这是一篇务虚的文章,面向前端的开发同学和团队,解读一个前端架构需要从哪些角度去建设和完善,补齐开发同学对技术架构的偏颇认知。kpxu至今已经做了10年的开发,8年前进入腾讯后就一直从事前端方面的工作。从拍拍的首位前端开发工程师开始,一发不可收拾。完全从零起步,一点点的推进腾讯电商的前端团队、技术、架构的发展,经历了拍拍、易讯、话费、彩票这些业务的征战和洗礼,这些年积累了不少在前端方面的思考和实践经验,这篇文章是在前端架构建设方面的阶段总结和感悟,分享给大家。从内容来看缺图少表,大段文字说教,会很枯燥,但耐心读下去的同学一定会有收获。


作者:徐凯鹏-腾讯web前端专家工程师
@IMWeb前端社区,若未授权禁止转载

什么是前端架构

  • 说到架构,很容易拉出一系列的概念知识点,像系统架构、软件架构、框架等等,这些不是今天探讨的重点,大家可以下去百度来理解。架构的本质是什么?其实也是一种管理。通常我们所说的管理,都是指对于任务和人员的管理,而架构管的是机器和代码。比如说,机器的部署属于运维的物理架构,SOA属于服务架构,那么,前端的架构指什么呢?

  • 长期以来,前端所处的位置是比较偏应用层,很薄的一层,而架构又要求深度和广度,所以之前在前端里面做架构,好比在小水塘里游泳,稍微扑腾两下就到处碰壁。但最近这几年来,随着一些列新的技术和概念的出现,前端的范围被大大拓展了,所以这一层逐渐变得大有可为。

  • 单纯从语言的角度来说,html、js、css是最简单最容易上手的开发语言,不考虑模块化、工具、压缩优化,任何人都可以快速上手,完成一两个功能简单的页面。在规模很小的项目中,前端技术要素彼此不会直接产生影响,因此无需架构相关的思考。由于前端语言这种灵活松散的特点,使得前端项目规模在达到一定规模后,工程问题凸显,成为发展瓶颈,原来孤立的技术要素开始彼此产生影响,各种技术要素彼此之间开始出现关联,要用模块化开发,就必须对应某个模块化框架,用这个框架就必须对应某个构建工具,要用这个工具,就必须对应某个包管理工具……这个时候,需要有人从比较高的角度去梳理、寻找适合自己团队的集成解决方案。而这一系列解决问题的工具和手段就是所谓的前端架构。

架构的组成

组件框架

  • 架构不等于框架这一点很好理解,相信大家都能够很深入的说明这里的差别,框架是架构的重要组成部分,架构决定框架的选型,框架决定架构的技术路线。架构围绕框架进行一系列的流程工具建设,从而形成完善自动的开发体系。
    +框架不等于类库,这里就是很多人困惑的点,你用的什么框架?jquery、underscore、linq、seajs、requirejs等等,每个人都能够列举一大堆。但这个是不准确的,一套编码框架是有一系列的元素组成:
    1. 开发模式,我们如何来实现代码的职责分离。以前整个前端是mvc中v这一层,而现在前端内部也进行了mvc的逻辑细分,Javascript的MVC框架现在很多,有的强化m、有的强化c。每一个框架其实都有其特点的,并且有越来越多的创新改造,比如现在最流行的是mvvm。有angular、react等等。我们是为了引入mvvc才把他们纳入到我们的开发体系,而不是因为他是一个好用的类库。
    2. 通讯,模块化、组件化是前端在推进开发模式过程中的一个过程产物,为了有效的进行组件隔离和独立,现在有各种各样的通信模型出来,不过由于实现简单,代码少,他往往是合入到某个类库里面,但本质也是一个类库。比较成熟的比如:消息总线、事件模拟、缓存中转、flux模型等等。
    3. 模板,我们用什么样的方式来集中的处理数据往html的转换过程,这里就不用多展开,这种类库现在太多了,光我们公司就有很多套,大家在代码行、缓存管理、预编译、运算性能、强大的语法等等各个维度不段追求各种极致。
    4. 基础类库 最后才是传统类库,相信现在已经没有同学会在项目中去约束团队中的dom操作、常用函数、方法、异步化等等各种很基础东西,这个时候我们一般就是引入jq、zepto、underscor这些封装好的东西就行了。核心就是为了改善编码生产力。
  • 对于框架的选型要从两面看,一是看该框架的本领,二是看你们团队的能耐。从经验上给几个点建议:
    1. 大工程应该尽量避开谷歌产品,他的很多技术开源项目都是玩票性质的,GWT、Closure、Darty就是前车之鉴。曾今提出过很多的新技术,到现在还是独家的,变出太大。包括现在angular,喜欢做断崖式升级,做做运营后台系统问题不大,如果是线上系统的话,每次升级就是一次人月神话中的典型焦油坑。
    2. 关注应用场景,像刚才说到的boss后台是一种;另外我的平台是否有沉重的历史包袱,需要兼容ie6,还是可以轻装上阵;产品对于seo是什么样的态度?是否需要考虑自适应?或者我的团队足够大,能够各搞一套?;产品特征是强内容还是强交互或者是游戏性。这些都是选择不同框架的主要出发点。
      • 这里也可以顺便展开聊一下现在前端产品的形态分类:
        1. 内容型Web站点 侧重渲染方面的优化,前端逻辑比重小
        2. 操作型B/S系统 以数据和逻辑为中心,界面较规整
        3. hybrid内置型,要处理缓存和一些本地接口,包括PC客户端和移动端。现在的本地应用,基于很多考虑,都变成了混合应用,也就是说,开发这个应用的技术,既包含原生的代码,也包含了嵌入的HTML5代码
        4. Web游戏,前端的逻辑非常重,在代码结构上要求非常高的可管理性和更复杂的设计模式。
        5. 桌面应用型,现在有一些PC端的混合应用开发技术,比如node-webkit和hex,前者的典型应用是XDK,后者的典型应用是有道词典,此外,豌豆荚的PC客户端也是采用类似技术的,也有一些产品是用的qt-webkit。这类技术可以方便做跨平台,极大减少开发工作量。
      • 从这些分类里面,我们这些年派生出了所谓全端和全栈的概念。但本质上怎么走还是要由所在产品的形态来决定。
    3. 没有最好,只有最适合自己的,基本上,针对每个平台,我们都可以列出一些主流框架,但不意味着你们都能驾驭得住。小马过马,老牛没过膝,松鼠淹个半死,就是这么回事。但无论我们选择什么框架或决定自己动手造轮子,都勿忘初心,技术必须让我们工作生活更为轻松愉快——我们只选择我们能驾驭住的框架,我们不能保证它在一年后是否会过时落后。
    4. 而且按照我个人这么多年的经验来看,任何框架都会过时,往往不是因为他不够好,而是因为一定有更好的出来。我们再选择一个框架或者一个类库的时候就要想好,未来我如何抛弃他。至少不能成为我们引入新的框架的绊脚石。现实的工作中很多的团队往往会陷入到年复一年的用今年的新框架去重构去年老框架代码的历史循环中去。对于引入框架如何尽量延长他的生命力,我个人的意见是选择框架时去追求概念,而不是潮流,当我的架构可以接受新的设计概念的时候才去考虑引入新的框架。用设计理念的选择代替框架的选择。之所以这么说是因为我观察到我们部门的后端架构的开发理念跟我进公司的时候是差不多的。

工具平台

  • 提到工具平台,大家很快就能跟自己的团队里面的一些工具联系起来。像grunt这种现在都是基本工具了,相信每个团队都有自己的打包编译、发布工具,但这些肯定不够。这里主要跟大家探讨一下,我们的工具体系要用什么的思路去规划和review,也看一下我们还有那些可以进一步去完善的点。我梳理一下我们可以并且应该通过工具平台去完成的工作,不完整的话欢迎大家来补充:
  • 可以看出来工具平台主要就是围绕我们的研发流程中的每一步关键节点去建设起来的,工具平台是前端工程化的主要生产力。工程化是这几年非常热门的前端概念甚至是一个很明确的前端发展方向。我们可以看看业界已有团队提出的各种解决方案,无不以这种思路来设计和发展的:
    1. seajs开发体系,支付宝团队前端开发体系,以 spm 为构建和包管理工具
    2. fis-plus,百度绝大多数前端团队使用的开发体系,以fis为构建工具内核,以lights为包管理工具
    3. edp,百度ecomfe前端开发体系,以 edp 为构建和包管理工具
    4. modjs,腾讯AlloyTeam团队出品的开发体系
    5. yeoman,google出品的解决方案,以grunt为构建工具,bower为包管理工具
    6. legos,腾讯电商领域的开发体系,现在京东,通彩在用
  • 纵观这些公司出品的前端集成解决方案,深入剖析其中的框架、规范、工具和流程,都可以发现一些共通的影子,设计思想殊途同归,不约而同的朝着一种方向前进,那就是前端集成解决方案。尝试将前端工程化中孤立的技术要素整合起来,解决常见的领域问题。
  • 前面提到工具平台是前端工程化的主要生产力,不同规模不用技术模型不同阶段的团队在工具平台的建设上会有不同的侧重点和优势,但共同的问题都不太能清晰去把握整个节奏,只能在遇到新的问题时一点点去完善补充。很难做到有节奏有方向去构建工具体系,这里我的建议是从多个维度去不断review自己成果,包括前面列举的按研发流程中的各个环节,这里抛出另外一个维度,是因为我总感觉从纯研发流程的角度来看问题可能固化我们的思考宽度,天然的约束了团队的工具平台创新,所以我习惯性的在客观list之上再抽象一组分类list,分类list的好处在于我们可以从更底层的概念上发散出新的具体环节出来。review的过程我建议从两个维度各自去思考一下,从而完善各自团队对工具平台建设的整体思路。

代码结构

  • 把代码结构这个点单独拎出来说,是因为这么多年的多工作中,我发现对于前端的架构这一点真的非常重要,通彩的项目前后经历过几次大的目录结构调整,每次都是伤筋动骨,让我一次又一次的反思,代码结构设计的灵活性在前端架构中的重要性。说一次影响比较深刻的:
    • pc主站时代,话费业务的发展非常依赖跨站的运营合作,我们通过bd在非常多的上嵌入了各种各样的快捷充值入口,有些站点还直接提供一揽子的全流程解决方案,包括从入口到页面到最后交易成功和信息反馈的定制,从而在后端形成大规模的成交积累,这些入口有各种各样的个性定制,初期我们拉了许多的分支,来处理不同网站的不同样式、不同用户交互逻辑。当时还是很规整的按照不同合作站点划分。但随着规模的推移,我们实在很难再承受这么大的维护工作量,无论是功能升级还是故障维护都很痛苦。原来的模式是我们从差异中去不断抽象公共模块,然而在路径管理、代码重构方面仍然很复杂,后来我们咬牙做了一个大的变更,做一套基础模型和标准流程作为入口,各个合作站点像基类和子类的继承、覆盖关系一样,对功能、展示进行重写。这个过程有很多各个环节上的技术改造,而与代码结构相关的东西我们就经历了很大成本。
  • 对于代码结构设计这一块的设计,我到目前为止也还在探索中,跟业务、技术选型的特征和发展都有着密切的关系,千人千面,但在这里的思考和准备上,我建议大家及早去做review,别等到包袱越来越重的时候再去追悔莫及。关于代码结构的设计上,我向大家推荐一篇很不错的文章,里面的设计思路有非常好的借鉴价值,是一位百度的前端张云龙同学写的《前端开发体系建设日记》,这篇文章是基于百度的fis框架,用一个模拟项目的构建过程把他的代码结构设计思路很清晰的传递出来。强烈推荐大家下去阅读一下。
  • 而我个人更倾向于给大家抛出一些问题,希望大家通过问题的思考来review自己的代码结构是否足够合理。
    1. 假设当前的团队放大10倍,业务复杂10倍,当前的代码管理还能跟的上吗?
    2. 如何避免开发人员之间的开发行为耦合?
    3. 如何支撑多特性、多版本的并行?
    4. 主路径按功能、按版本还是按渠道?

开发规范

  • 不要小瞧规范的威力,可以极大的提升开发效率,真正优秀的规范不会让使用者感到约束,而是能帮助他们快速定位问题,提升效率。
  • 一般来说开发规范指的是编码规范,开发在写代码的时候要注意什么,什么不能做。但这里我希望能把这个概念再放大一些。平时在研发管理中,我们会发现无论怎么去强调跟进,大多数开发同学们的输出总是跟自己想要的东西差那么一点点。不是说他们的代码不合格,而是往往在设计思路、模块拆分、结构分层或者其他方面不太合意。但一般又感觉不知道该怎么去说。最后往往就将就下去了,时间一长就越看越不对劲。所以我建议在开发规范上我们可以尝试一点点把这些方面可以明确下来,并且在大家共同认同后落地到规范上。
  • 对于规范来说最关键的是执行落地,在我的团队里面有个基本的原则,我们从来不相信只能靠开发人的自觉和频繁的代码reivew才能保证的规范是长期可持续的。这对团队来说也是负担。每当有一个新的规范建议提出的时候我们都会有一个问题,这个规范能不能用工具来自动执行或者自动检测。在通彩的legos平台上除了完成基本的代码编译构建任务以外,我们把大量的开发规范条款做成功能,在代码提交或者构建的时候去自动执行。给到开发提供了很大的便利,要么提交不了获得系统的检查反馈修改好再提交,要么构建的时候平台帮他完成。坚决不把问题入库留到以后再处理。

流程边界

  • 流程边界设计是架构设计的一部分。先说边界,淘宝的前端边界一直是重构+前端的开发模式,从出设计稿开始一直到最终的交互、数据整合页面输出。腾讯大多数的团队都有专门的重构团队来输出高质量的html+css,前端团队专心对付页面交互和页面逻辑组装。乍一看好像这个是在公司层面去设计的岗位分工,跟架构没啥关系,其实不然。在07年以前互联网这个行业基本上是没有前端开发这岗位的,大多数工作由后台开发包办,前端的出现是公司整个大的技术架构进化的结果。而后面重构开发岗位又是前端和设计岗位的技术架构进化分拆的结果。随着技术的持续完善,这种通过岗位变迁实现技术架构升级的情况会越来越少。而架构层面新的变化将来自于岗位自发的对自身工作内容、职责的重新定义,也就是这里说的边界。
  • 举个例子,随着移动应用的兴起,越来越多的前端团队开始承担起app客户端的开发,随着nodejs的兴起,越来越多的前端团队开始承接后端轻逻辑的开发,随着前端与后端研发节奏的不匹配越来越严重,更多的前端团队开始通过一些php承接接入层的开发。这里面很多来自于前端团队自发的优化,这种优化需要团队的架构师敢于去打破原有的边界,跟大团队一起重新定义新的工作边界,从而形成前端架构领域的放大和寻找更多技术创新的机会。回顾这几年的D2大会、Qcon、架构师峰会的前端内容,我们会发现前些年的性能优化、框架封装、设计模式的内容越来越少,而由技术跨界所形成的如服务器支出、h5增强、hybrid、桌面这类前端新领域技术越来越多。这个是前端架构的发展趋势,我鼓励前端的团队们结合自己的实际情况从不同的方向去尝试探索新的岗位边界,为自己团队的前端架构进化打开新的空间。
  • 再聊一下流程,就是说的研发流程,这个比较好理解。举些例子大家就明白了:
    1. 很早之前,我的前端团队有个分工最让人纠结:活动开发,繁杂、重复、总在调整。我们自问“如何让开发不用参与到活动开发流程中去?”,于是我们开发了一个活动开发平台,运营从设计同学拿到设计稿后直接上传平台,然后开始按照自己的需求画热区、配参数,自己验证发布上线。前端开发只需要补充新的运营组件上去就ok。由于整个平台经过一次性功能测试,后续新的活动也不用再走测试流程了。这个流程上的改造最直接的结果是平均2天一个的活动开发,变成10分钟1个,还不需要开发参与。前端团队的架构也得到了一次大幅度的提升。
    2. 功能的管理后台开发工作也是一个资源消耗大头,权限管理、复杂的配置管理、重复而毫无新意的工作让前端开发兄弟们苦恼,负责的同学还难以获得能力的成长。“如何让开发不用参与到运营管理后台的开发中去?”,然后我们设计了xboss运营后台开发工具,通过封装常见的后台组件、标准化运营操作接口格式和规范、统一操作流程和管理后台的产品体验。现在只要后台开发按照指定的格式和参数与开发好接口后,他们可以自己快速的在平台上搭建想要的管理界面,几十分钟轻轻松松完成,不要需要跟前端各种沟通、联调。架构优化的价值再次体现
  • 很多的前端成功技术和成果都来自于对原有流程边界的改造。好的架构师不会再既定的框架下去苦苦挖掘,在泥坑里面打滚,换块空地换个视角,可以做的更多。

团队理念

  • 不同的团队的架构模型必然不同,最好的架构一定是最适合团队和业务的那套架构。但在同一个团队和同一个业务中,两代架构师或者两个不同理念的架构师会带着团队走向截然不同的方向。再好的架构也禁不起这样的撕扯,最终往往是推翻再来。相信大家或多或少会有类似的经历和感悟。
  • 一个架构除了前面那些看得见摸的着能够带来实际好处的组成元素外,还需要一个统一的牵引力去影响他的成长迭代,这个牵引力就是团队理念。统一的团队理念可以帮助我们在架构演进过程中形成统一的技术选型、解题思路、价值观念。减少在这个过程中无谓的争执,甚至最后出现“都试一下”这种费时费力不负责任的结论。
  • 团队理念来自于团队对自身实力、业务特征、业务发展方向、技术挑战点等等常识性问题的明确和共同认可。务虚但能起到最关键的作用,就像我党“要做人民的子弟兵”一样,在队伍变大时,这句话就是最有效的管理手段。下面简单列举几个例子,如果感兴趣的同学可以基于这些理念的理解再去了解一下这些团队的技术架构发展路径,感受就会明显的多。

经验沉淀

  • 技术架构最强大的地方在于控制,好的架构不担心差的程序员,它能把编码带来的风险控制在局部,让坏的螺丝能很轻松的被更换掉,能够让各种奇葩的代码颗粒自动排列成整齐的可管理状态。但好的架构风险在于持续传承,他一定是诞生于少数人之手,但依赖大量不同能力、视野的同事进行应用和维护。除了团队理念的统一,经验的沉淀和传承体系建设,同样必不可少。但怎么做怎么建设就不用展开了,这个点不神秘。

小结

前端架构是指在前端开发工作过程中用于提升开发效率、质量、性能和可维护性的保障体系,个人的认知结构如下:



若你阅读该文中有什么疑问,欢迎在下方评论区留言,我们会选择部分问题解答
编辑于 2017-04-20 15:26