面向开发者的工程化 CLI 中台:分层插件架构

953 阅读6分钟

相信提到前端工程化,大家或多或少都有些自己的理解


工程化:规范、流程...


规范:代码规范、git分支规范、组件规范…

流程:接口定义、开发、测试、构建、发布…


其中研发流程中又会涉及到很多工具和平台


工具:脚手架、mock、webpack、ESLint…

平台:gitlab、LowCode、web IDE…


虽然涉及了这么多方面,但是工程化的目的是一致的


往近了说,是收敛和约束,是沉淀和降本提效

往远了说,是可维护性/稳定性/质量…


就目前(2019/11)常见的开发模式而言,在工具层面,CLI 会是连接开发者和工程化的枢纽,本文会从 CLI 设计出发去聊聊工程化


起因和思考


在落地工程化的过程中,可能大家都遇到过一些问题,以下是我体会比较深的两点(当然每个人的经历都不同,不能代表所有公司的现状,本文只是从这两点出发而引申出一些思考)


  1. 混用技术栈
    由于一些历史原因,可能一些公司也遇到过混用技术栈的情况,vue-cli / create-react-app / bigfish 这类针对特定框架的工具都是不适用的

F0A2FB28-4C7D-4672-B0A9-7291A66235A6.png

  1. “不负责任”的脚手架
    GitHub 上出现过很多脚手架,但现在基本都不温不火了,究其原因,大部分脚手架内部没有去做收敛,直接暴露了一堆配置文件,假如脚手架更新了,很难通知到用户,这导致了要在所有工程里面去落地一些新的工程化最佳实践,成本很高,尤其是一些大型的团队,可能前端工程接近上百个,这就带来了 1+1 < 2 的问题


针对这两点有什么解决方案吗?答案是有的,NUT + RDE


  1. NUT:微前端框架,虽然对外宣称是微前端框架,但是我更愿意用 frameworkless 来描述他,nut 在设计上更彻底,微前端只是 nut 技术栈融合场景的一个分支,nut 没有强调基座/子应用的概念,每个 nut 应用都可以作为基座或子应用,包括每一个 nut 应用内部也是允许混用技术栈开发的,无框架和融合这两个基因是刻在骨子里的
  2. RDE:用来收敛脚手架的 CLI 工具,用 docker 封装脚手架,屏蔽内部实现细节


这些一定程度上解决了部分问题


但是


  1. NUT 有一些很好的特性,但是要接入就要接纳他的全部设计理念,有些已有工程存在迁移成本,但如果把他的部分能力拆出来,而不是提供一整套的解决方案,能够受益的工程会更多,落地的阻力也会更小
  2. RDE 在工程化方面缺了两个重要的特性:沉淀和孵化
    由于底层过于开放,无法做到更细粒度的沉淀,缺少标准也导致业务组同学很难参与共建并沉淀东西下来,这意味着工程化这件事业务组同学想要参与,也只是一次性的反哺,依然无法以一种简单的方式沉淀和落地最佳实践,但是相比之前的刀耕火种,RDE 的确指明了方向


如何去设计


在开始前,我们先来看看传统的单层插件架构是什么样子的


D212A022-5300-4EDC-8A1F-0511BAB8CDF6.png


一个核心对应一些插件,由核心提供能力给插件


但是在工程化这样一个特殊场景下,我们需要思考下,core 应该是什么


答案不是唯一的,grunt/gulp/webpack/rollup/parcel-bundler,单单构建相关的就有这么多,何况工程化涉及的点远不止这些,比如 mock / lint 等等一系列研发流程


不过如果只是针对 业务工程 的构建打包,你可能会说,选 webpack 啊,这么多人在用,好的选型 是 适合当下 的选型。横向比较的话,webpack 的确独占鳌头


但是这里会有如下一些思考


  1. 如果基于 webpack 进一步定制呢?比如 wepack + vue,类似 vue-cli 这样的工具,定制的往往更有针对性,更能提效,但是如果后面需要迁移技术栈到 react 呢?又要写一个 react-cli,之前在 vue-cli 上积累的生态就丢失了,如果不是同一拨人开发的,使用方式可能也会发生变化
  2. 假如将来出现了比 webpack 更好用的工具,之前的插件架构移植的成本以及旧插件平滑迁移的问题


Q:webpack 好用吗?

A:好用。

Q:那 webpack 是未来吗?

A:不一定,就像 gulp,总有更好用的工具出现,工具只是手段,做工程化是为了将方案更好更快地落地下来,这种能力才是我们追求的。


redux 作者在 twitter 上有句话,我很认同


不要写太灵活的模块,因为你永远无法预知未来的变化,不如写一些容易移除的模块


我们需要设计一个更通用的模型,单层的插件架构并不能很好地适应 业务发展的需求 和 未来的变化,我们追求的不仅仅是当下的好用


在设计时遵循这样的基本原则:


  1. 不相信一个东西能够长久存在,不管是工具还是框架,我们需要在某些垂直领域深耕,但也不会选择吊死在一棵树上
  2. 不把底层能力直接暴露工程,暴露的底层能力对于将来的迁移工作来说是“作恶”


Xnip2019-11-329_13-46-51.jpg


这也就是标题中提到的分层插件架构


在这种架构下,工程化是一座大厦,每一层都有参与共建的人,会形成自己的生态,下层可以使用上层的生态,在这种情况下,就算最下层被摧毁了,大厦依然会继续存在


(N、M、X分别为每一层独立的插件数量)

CCA8EFAD-66B6-42C0-94FB-36C5BEB5D31E.png

Xnip2019-11-329_13-48-31.jpg

8A685D5A-1906-4629-8122-1CA76E3C4E03.png

这样的能力,机智如你,应该想到了中台的概念,对的,他提供了 CLI 中台 的能力,你可以直接使用上层 driver 快速定制出适合自己场景的工程化工具,而且上层 driver 的生态你也是完整拥有的(典型的比如 driver-webpack,你可以定制出 driver-vue/driver-react/driver-microfrontends,同时 driver-webpack 这一层所有的插件你也是可以直接继承过来的)


写在最后


最后,谈谈自己想要的工程化是什么样子


开发者只需要关注页面维度的开发,通用的流程、平台和场景接入在框架层面就屏蔽掉(登录鉴权、错误上报、性能监控,pc、h5、单页、多页、小程序…)


类似 serverless,工程化做到最后可能就是 engineeringless,让开发者感知不到专业工具的存在,web IDE 在这件事上是一个很好的突破口,上 web IDE 前,在研发核心流程中 CLI 是连接开发者和工程化的枢纽,上 web IDE 之后,平台能力承担了这些,当然底层还是需要有框架和规范去做支撑