何为工程化:
工程化即面向某个产品需求的技术架构与项目组织。工程化的根本目标即是以尽可能快的速度实现可信赖的产品。尽可能短的时间包括开发速度、部署速度与重构速度,而可信赖又在于产品的可测试性、可变性以及Bug的重现与定位。
从2016年的一个零基础的前端小白,到2020年的一个在前端领域摸爬滚打了四年之久的老兵(一直在一家公司工作),随着时间的推移,知识的积累和经验的增长,也对前端有了越来越深刻的认识,借助2020年年前的一次前端项目的规划,想谈一下自己眼中的前端工程化。
契机
随着公司产品化进程的推进,越来越多的业务线被迁移、整合到一套相对完善、稳定的后台系统内,对于后台这样的转变,前端也必须做出相应的改变。
原来的方式
不同的项目有不同的前端人员开发和维护,有着独立的仓库和技术栈,从头到脚都是一个完完全全的独立的项目,无论是PC端,还是H5端疑惑小程序等。
这样做的背景:
- 对接的后台系统不统一
- 与其他项目没有任何共同性
- 没有可复用部分
这样做的优点:
- 项目独立,与其他项目耦合性低
- 专人开发和维护,责任落实方便
- 代码单独仓库维护,文件量少,好维护
这样做的缺点:
- 技术栈无法保证一致(不同的开发人员根据自己的喜好和特长进行选择)
- 单人开发和维护,文档维护几乎为零,项目知识沉淀少
- 换人维护成本太高,需要信任从新了解一边新的技术框架、库等
- 时间久了,没人知道项目地址在哪,也没人知道如何启动,发布和测试
现在的情况
越来越多的业务线归纳合并到一个系统内,为前端工程化提供了契机,随着公司的人员精简和项目统一,需要更高标准和更高效率的进行模板化开发类似甚至相同业务流的系统,在这种状态下,如何实现前端各项目间的公共部分的共用,是提高效率和降低开发、维护成本的首要解决问题。
我的思路:
为了解决或者避免,人走项目无人知晓的情况(因为人员流动问题,导致很多遗留项目无从得知详细的细节),我思考,能不能采用多项目,单一仓库维护的方式进行项目管理。
这样做的优点:
- 有利于统一技术栈
- 可以将多个项目统一管理,不至于无人知晓在何处
- 无论是单人开发维护还是多人,都能对项目集合下的项目有一个概览,不至于在新介入时一筹莫展
- 可以提取共用部分,降低开发成本
这样做的缺点:
- 单一仓库的项目量特别多的时候,仓库代码量会膨胀
- 难以保证NPM依赖的稳定性(不同的项目需要安装不同的依赖,如何保证不冲突,不覆盖,版本统一)
- 不同端之间的解决方案有所区别,如何很好的区别对待
- 代码组织维护起来需要花更多的精力(文件很多,文件夹也很多,稍不注意可能会误操作文件)
基于以上缺点,我采取以下相应措施进行规避和化解:
对于代码量膨胀的问题,没有很好的解决方案,唯一能做的就是,node_modules不进行上传,通过本地安装依赖的方式运行本地代码。
- NPM以来的稳定性,我做出了以下方式:
即我对每一层的项目文件夹都对了自己的依赖维护,比如,类似react,react-dom,react-router,mobx,mobx-react这样的公共依赖,我会把它提升到整个programSet的目录下,而针对不同端的一些依赖,则会放置到二级目录下,针对具体的某个项目(app1,app2…)里面又可以安装自己需要的独特版本的依赖。
- 不同端之间的解决方案不尽相同,包括打包方案
我将webpack-config提到programSet下,根据不同的端的项目进行了分类配置,这样彼此之间互不影响和干扰,打包命令,则通过注入项目的类型,文件夹名称及运行模式等来解决,如下图:
这样通过NPM脚本插件就可以一目了然的知道自己要运行的项目,点击即可运行,打包。
- 公共部分的提取
将类似于网络请求,公共的controller,以及一些通用的util方法,还有一些共用与多个项目的组件,可以提取出来,放置到common层,借助ES Module的帮助,可以实现模块的共用。
关于业务逻辑层的共用,我曾做过其他的尝试,比如曾使用TS开发过一套基于公司后台系统接口的前端js-api–sdk,这种方式的好处就是,你可以完全以安装里来的方式使用接口api,而且一套完整的网络请求的解决方案都是内置的,无需使用者关心,只需要在项目的初始化部分初始化sdk的配置信息即可,而且基于TS开发的sdk还有非常好的职能提示效果,对开发者极其友好,但是不好的地方就是,业务的不成熟和易变更,导致需要花费大量的经历去维护和升级sdk,而在意需求为核心的团队内,没有相应的人力支持到此项目,所以采用了一段时间后也就不了了之了。
- 如何快速的相应需求搭建新的项目:
我在每一个端的项目集合内都搭建了一个极简的模板项目,包括了一套的路由规则的配置和简单的页面切换功能均已实现,如果需要搭建一个新的项目,直接基于模板项目拷贝重命名,并在最外层的package.json文件里添加相应的运行、打包命令即可直接跑起来。我尝试过本地搭建通过命令行构建新项目的脚手架,但是适用与单一项目的场景,对于这种大的项目集合的项目管理来说,不是很合适,相反,简单的拷贝和命令行的添加就可以完整的搭建起一个项目,这种方式倒简单轻松的多。
关于文档
一个人经验来说,无论大项目还是小项目,文档都是至关重要的,除非一个人可以保证他可以维护一个项目到项目下线,但是你也保证不了不存在项目再次重启上线的可能。所以文档对于一个人员流动比较大的互联网企业的技术团队来说,至关重要。
为此,我采取的方式比较极端,那就是几乎疯狂的严格要求,只要出现一个文件夹,就要在此文件夹内存在一个对此文件夹进行功用描述的README.md文档。这样一来,就强约束了创建文件夹的人,要对他所创建的文件夹和其中的文件有一个特别明确的认知,该文件夹是放置什么文件的,这些文件都是用来干嘛的,都要用简单的语言文字描述清楚。
这样做有一个好处就是,当你在代码管理平台上(gitee,gitlab等)打开某个文件夹的时候看到的不仅仅是几个文件的蓝色link那么冰冷,具体某个文件干嘛的,如果命名又不是很具象化,那么你根本无从得知,只能一个个的打开文件,阅读代码,才能知晓一二,但是每个文件夹都存在一个README的好处就是当你打开这个文件夹的时候,除了几个冰冷的文件链接之外,你还有一些描述性的文档可读,这可以大大的帮助新人理解这些代码的功用。