前端有架构吗?
从事前端开发的你,不知有没有被问过:「前端有架构吗?」
问你的人的身份,可能是你的 boss 或上司,可能是后端同事,也可能是前端同行;问你的人的目的,可能是刁难,可能是嘲讽,也可能是请教。
前端开发
众所周知,做前端开发所依赖的核心技术就是 HTML、CSS 和 JS,就像好基友一样形影不离,我们将它们仨亲切地并称为「三剑客」。
经过这二十多年,尤其是在 V8 引擎及 Node.js 出现之后,以「三剑客」为基础的衍生技术如雨后春笋般大量出现,前端及其关联社区与前端工程师这个职业得到了空前的蓬勃发展,甚至让很多人觉得一个前端工程师不仅仅可以做 web 前端开发,还可以写后端,替代客户端工程师——前端技术一统天下!
工作内容
除了做网页,前端技术还能应用于命令行工具、客户端应用、服务端应用、聊天机器人、爬虫、IoT 等场景。只要脑洞足够大,就不怕场景不够多。
然而,绝大部分的前端工程师在工作中都会接触到这些吗?
试想一下,自己的工作历程是不是这样的——
在一家 150 人规模以下的创业公司,可能业务还在摸索期,需要不断地快速试错以找到可以铆足劲儿去发力的点。这时前端团队也没几个人,可能就三五个吧,并且 leader 不是什么大牛,也没有一套方法论作为团队建设的指导,也许你是这个团队里实力最强的。
这个时期所需要的就是能够快速迭代产出成果,然后去验证是否有效。根本不会给你时间去思考、规划前端团队的发展方向与基础设施建设。如果特意花费时间去做这些,没准儿公司会认为你「不务正业」,到时 KPI 打个不及格。
经历一段时间的焦头烂额,在此期间工程目录、代码提交很可能都很随意,并且没有 code review。有空闲下来回头一看,代码一坨一坨跟那个什么似的,实现与「优雅」这个词绝缘。
随着业务的快速发展,项目、应用越来越多,团队人数也越来越多,然而规范约定、基础设施依然几乎没有。在业务线做开发的前端,也不太会想着整个团队的工具统一,自己怎么爽就怎么来。最终导致一个团队用了多种视图层库、多个组件库,给收敛技术栈带来很大阻碍。
终于,公司的业务开始走上正轨,前端团队也已经有二三十人了,胸怀大志、急他人所不急的你觉得再这样野蛮生长下去是肯定不行的,靠堆人力去满足快速发展且多变的业务需求是非常低效且低级的方式,必须要有技术上的基础设施去支撑!即使公司层面不允许工作时间去做这种长远看来对公司是百利而无一害的事情,也要去做,就业余时间去做!
在所有基础设施中,最初级、最能直接体现出开发提效成果的,就是高度抽象的 UI 框架。经过了不知多少个的「下班后」和「周末」,可算搞出了个能够满足一定业务场景的,在自己负责的几个应用中初见成效。
正当你为自己所做的事情如期望中那样得到了收益而感到欣慰时,突然有人冒出来质疑你所做的事情,并且有可能就是前端团队中的。还好有其他人对你做的事表示认可,觉得有价值,让你有动力在这件事上继续下去。也许他是个后端开发,愿意去用,或愿意帮你在部门中推广。
你不断地给 UI 框架增加新的功能,并想方设法去改造旧系统。在公司拓展业务所需要的新应用和以前老应用的维护中,你所做的东西确确实实节省了不少人力和资源。在有新的一批后端开发入职时,还会邀请你在新人培训上给他们讲解如何使用你所开发的 UI 框架辅助完成工作。这结结实实地打了当初质疑你的人的脸。
后台系统页面的常见模式就是供数据 CRUD 的列表页、表单页和详情页,当把支撑这些场景的交互和数据处理的核心逻辑都已经抽象了之后,你发现再怎么完善 UI 框架也不会有像之前那样比较明显的效率提升,顶多是优化了交互和开发体验,使功能更稳定而已。
你陷入了思考:「该做些什么才能继续为开发提效呢?」
之前做的 UI 框架,是对交互逻辑和数据逻辑进行了高度封装,并提供了大量的 CSS class 和工具方法。虽然使在做页面时可以少写很多 CSS 和 JS 代码,但对于 HTML 代码来说并没有减少。
貌似找到了该突破的点,但要怎么去做呢?
左思右想,你突然灵光乍现,想起了自己曾经用过的基于「世界上最好的语言」开发的博客系统——WordPress。既然后台系统页面如此模式化,何不效仿 WordPress 将不易变的部分作为「主题」,易变的部分作为「文章」?
这样做会带来另外一个好处,就是将页面代码数据化了,有什么纯前端的问题修改就只是数据修正,而不用走冗长繁杂的运维发布流程。日后如果公司有了自己的设计语言,再加入可视化搭建的特性,业务后台系统的开发和维护前端就不太用参与了!
理想情况下,产品经理用已有物料拖拖拽拽生成「原型」,该「原型」就是最终界面;业务功能确定后,后端开发定模型、写接口,然后配置界面的数据展示。这样一来,业务系统迭代的整个过程中,基本可以忽略前端这个角色了。
那么前端干什么呢?在这样的协作模式下,前端的主要工作就是完善物料库,并且让产品经理和后端开发使用起来更方便。这种提效方式所带来的收益,与开发 UI 框架相比,根本不是一个层次的,想想都觉得兴奋!
然而,理想的丰满遮不住现实的骨感。听到你的想法的人,要么质疑地问你一些问题,要么嘴上表示支持心理暗地讥笑——不想些怎么让业务发展起来的事情,整天想什么乱七八糟、花里胡哨的东西!
你觉得心里憋屈,认为他们目光短浅,看不透本质。但为了自己所认为所坚信的「正确」,就算没有人在心理上或行动上有所支持,也要朝着那个方向努力,尝试做一把!
经过一段时间的折腾,你开始感到有些做不下去了。一方面是因为,虽然 Node.js 的出现让前端开发人员也能够开发服务端,但数据库等服务端开发领域所需知识和思维方式匮乏,致使设计很不合理,写出来的程序也不好;另一方面,公司层面不期望你投入较多的时间在短期内对业务发展没有太大帮助的事情,就连 KPI 的指标设定都是很业务化的,等 KPI 评分时分数肯定很低。
在这家公司里,你也算是「老员工」了,对公司的品性也较为深刻了解,自觉自己所认为所坚信的「正确」在这里得不到认真对待,至少很长一段时间之内是,你甚是失望,甚至绝望。其实,你早如此感觉,只是不愿面对,总是希望自己的信念能够多多少少影响到组织的认知,然而徒劳。
从 UI 框架到页面数据化,在做这些事情时你都是独自一人、孤军奋战,忽然心里感到一丝悲凉。你最终黯然离开,想去大厂里去看看,也许那里能够让你实现技术理想。
当你真正进了大厂,而且是个业务部门时,你会发现做的事情和之前并没太大差别,仍然是业务为重。不同的是,可能你的领导和身边的同事,对你的想法是真心认同的,他们会尽力支持你想做的事情,并为你提供帮助。
你幡然醒悟:无论在小厂、中厂还是大厂,只要是在业务部门,UI 框架、命令行工具基本就是在技术上所能做的极限,要想更上一层,就得在平台部门。
提效方式
前面多次提到了「提效」这个词,它是什么?简单粗暴地讲,就是缩减业务需求的研发时间,这是所有开发人员所追求的。如果有可能,只需需求方自己动动手操作下就完成。
那么该如何提效呢?我所能想到的,大概有:
- 基于各视图层库的具有一致 API 的 UI 框架;
- 能够覆盖整个研发流程的命令行工具;
- 将一份源码编译/转译成不同目标平台代码的工具;
- 页面数据化并支持可视化搭建的平台。
这几点,每个展开往深了弄都是很有价值的事情,需要耗费很多心血,甚至可以作为一个产品或开一家公司了!
前端架构
在继续往下进行之前,先让我们来稍微探讨下「前端有架构吗?」这个问题。
有架构吗?
「架构」是什么?架构是一组抽象概念,像「人」,像「宠物」,让你不必关注他是谁,它是什么动物;架构是一张图,让你能够清楚地了解不同事物是怎么归类的,它们之间是如何联系到一块,如何进行协作的;架构是指导思想,告诉你什么该做、什么不该做,指引你把代码写到正确的地方;架构是一套方法论,让你知道在哪些场景下遇到哪类问题该怎样去解决……
引用维基百科的话——
Software architecture refers to the fundamental structures of a software system and the discipline of creating such structures and systems. Each structure comprises software elements, relations among them, and properties of both elements and relations. The architecture of a software system is a metaphor, analogous to the architecture of a building. It functions as a blueprint for the system and the developing project, laying out the tasks necessary to be executed by the design teams.
基于上述描述,如果前端开发只是单纯的静态页面,即只有 HTML 和 CSS,或 JS 只作为添加特效使用,不操作数据,没有通信,那么可以说「前端没架构可言」。但,现在从事前端开发的人,有几个人的工作是这样的呢?
我想,从事前端开发的你的工作不是做页面,而是应用开发吧?那么,架构就是必不可少的了。你也许会疑惑:「我连这听起来逼格很高的词具体是指啥都不知道,怎么可能会有?!」
之所以无所察觉,是因为你没有刻意去思考并进行架构设计。想想看,你是不符合以下情形:
- 根据社区里总结的最佳实践,或者与他人交流时受到启发,在开发时将代码逻辑拆分成不同模块,并将几个具备一些相同特征的模块放到一个目录下;
- 用 Umi 或 Vue 全家桶开发单页面应用。
这两种情况都可以说是使用了分层架构模式,前者是你无意间进行的,后者是人家帮你做好了的。
好的架构?
既然「前端有架构吗?」这个问题的答案是肯定的,「什么样的架构是好架构?」就成为了下一个问题。
在说「什么样的架构是好架构?」之前,先插入另外一个问题,有兴趣的话可以先行思考下:一个足够复杂的前端框架,与浏览器、操作系统之间有什么相同点?
回归正题。我认为一个好的架构应该是这样的——帮公司更轻松地赚钱。这点是最重要的,对于一个企业来说,如果软件不能让自己赚钱,为什么要用它?帮助公司赚钱的方式无非就两种,「开源节流」。「开源」比较难,需要了解行业并洞悉商机,对人本身资质的要求太高;「节流」相对就简单了,减少研发投入,即上文所说的「提效」。
第二重要的,就是「稳定」。一个差不离儿的架构,至少得能支撑业务发展三五年吧?虽然公司未必能活那么久。这就需要在做架构设计时能够面向未来:一是业务的未来,二是技术的未来。面向未来的架构必须扩展性好、足够灵活,这样才有可能应对各种业务场景及突如其来的业务变化。
以上是我觉得一个好的架构的两个核心标准,每个点都会牵扯到很多事情,就不在此多说。
在对一个系统进行架构设计时,会用到多种架构模式,如:分层模式、管道和过滤器模式、微内核模式、微服务模式、MVC/MVVM 模式等。在实现时又会用到多种设计模式、数据结构与算法。
因此,要学习并掌握它们,然后根据(潜在)业务目标与(潜在)应用场景去选择最适合的运用到架构设计和框架实现当中。
核心原则
在做前端架构时,我认为该遵守几个基本原则——
第一个是「以不变为中心」。
软件开发的本质就是操作数据,放在 web 开发的场景,后端是存储、获取数据,前端是收集、展示数据。
数据在前、后端流转时,数据的基本形态不会变:基本类型、对象、列表;数据的传输协议也不会变:HTTP、WebSocket。在前端开发中,离它们越远、离 GUI 越近的东西就越容易变。
所以,首先要做的就是梳理出哪些东西是不易变化的,哪些是很容易就变了的。
第二个是「各层皆可替换」。
将根据易变性梳理出的模块按职责进行分层,定义好层与层之间的对接协议(接口)。除了因自身进化需要,对接协议是基本不会变的,也不应去改变。以此为前提,各层实现可在业务需要或技术升级时进行替换。
第三个是「视图层尽可能薄」。
视图层的职责是展示数据,理应只有交互逻辑,而大多数前端在写 UI 组件时会掺杂较多的业务逻辑,使视图层变得很是厚重、臃肿。这样一来,业务逻辑不利于复用,也会增加视图层技术的迁移成本。应将业务逻辑进行抽象,并提取到领域层,让视图层保持纯粹。
由于视图层的易变、多样,并想让它尽可能薄,最好有什么方式能够增加它访问逻辑层的成本,就像前端只能通过网络请求访问后端一样。
忽然想到在做业务开发时有遇到过这种架构,你有印象吗?没错,就是微信小程序!微信小程序的架构是将逻辑层与视图层放到不同的线程中运行,从而做到了天然隔离,它们之间交流的媒介只有「数据」:
图片来自微信小程序开发文档
微信小程序是建立在客户端应用提供一些原生能力基础之上的,那么在浏览器中能够达到相同或类似的效果吗?当然可以!浏览器提供原生能力,视图层运行在 iframe 中,逻辑层则在 web worker 里:
图片来自《小程序底层实现原理及一些思考(2)》
觉不觉得这很像「微前端」架构——据我理解,简单来说就是一种能够让不同技术栈的模块同时运行在浏览器中,它们可以是组件也可以是应用,并且相互之间能够通信、协同工作的架构模式。
基于这种架构,可以开发出一个类似于浏览器、操作系统的「超级 app」,成为平台级应用。
如果你在平台部门,上文说的也许就是你要面对的事情。
开源项目
前段时间,某厂的前端团队开源了一套组件库,当时我在想:如果做不到比 Ant Design 优秀,开源个组件库的意义在哪?
出自蚂蚁金服的 Ant Design,无论从设计(视觉设计、代码设计,各种设计)还是从实现来看都已经很优秀了,API 设计十分考究,国内很难有出其右的作品。
如果说在某个视图层技术或某个端没有其对应的实现,与其自己从头造轮子,还不如实现一个在那个视图层技术或那个端的 Ant Design 版本。
之前我一直认为经过几十年的发展,GUI 的交互形式已经相对固定,不太会有什么突破,如果已经存在了一套很是优秀的交互模式库,后来者若是没有什么能够与其抗争的亮点,在竞争上无疑是以卵击石。
直到听到叔叔说:
开放的意义并不是代码,而是有自身对交互的理解,如果做不到这点,那开放组件库就没有意义。
一开始没怎么理解这句话的内涵,之后的几天时不时会想到这句话,琢磨其中的含义。之后忽然明白了——这不就跟写文章一样吗?!写作难道是为了让别人看到自己的文字?当然不是!是想用文字记录并表达自己对这个世界、人、事、物的理解。难道已经有人写过相同或类似观点的文章,且写得十分好,自己就不能写了吗?当然不是!
原来如此。
其实任何带有创作性质的行为都是一样的,都是通过某个途径来表达自己的思想,写文章是,写代码是,绘画是,做菜也是。正如荒木老师的书上所说——
《荒木飞吕彦的漫画术》封面
最近,我要开始做一个「大」项目。实际是前几年就想做的,只不过当时没想好到底要做些什么,但核心理念是一致的——反混沌!连项目名都起好了,就叫「Anti-chaos」。
为什么要做这么一个项目?还不是因为前端圈太混乱?虽然与前些年相比稍微好了那么一点,但跟 Java 圈相比,乱太多了。我希望「Anti-chaos」能成为盘古之斧,劈开混沌,清者为天,浊者为地。
那么「Anti-chaos」要做些什么?就如刚才所说,这是一个「大」项目,因为它基本要覆盖当前前端开发的方方面面。
我并不是想开发一个大而全的框架,而是要遵照「反混沌」的思想拆分成多个小项目,每个都是解决某个固定场景的问题,它们可以组合并扩展成适合某个团队、企业的解决方案,从而使前端开发乃至前端圈变得更加有序。
之前我也是基于类似的想法,想让「前端工程师」这个职业相关的一些事情变得更加标准、有序,然而这件事操作起来实在是太困难了,比安静地写代码难上不知道多少倍,所以目前处于搁置状态。等「Anti-chaos」有所成效之后,再看情况是否重启那个项目吧。
思想总结
作为前端工程师,在业务部门所能接触到的技术以及眼界的提高是有限的,一是在做业务时用不上什么太前沿的技术,二是业务部门的性质不会允许也没有资源让你做太多深入的思考和尝试。
要想真正地提升自己的技术能力和眼界,最好还是去平台部门吧!刚开始时也许会觉得很吃力,这是因为你为了适应环境而在进行思维模式的转变。等你适应了,你就会发觉自己在思考问题时与后端越来越接近,也会越来越觉得无论做前端还是做后端,所需要的知识和能力是差不多的,只是要解决的问题不同。
一个人的水平不能用年龄和年限去衡量,要看他有多少经历,都经历过什么。
本文主要阐述了我最近一段时间对前端开发、前端架构以及开源项目等方面的思考及现阶段的理解,不一定对,但是我目前的见解。
正所谓——
参禅之初,看山是山,看水是水;禅有悟时,看山不是山,看水不是水;禅中彻悟,看山仍然是山,看水仍然是水。
以上。
作者:欧雷
来源:InfoQ