字节前端提效之路 —— 从「脚手架」到「工程方案」

字节前端提效之路 —— 从「脚手架」到「工程方案」已关闭评论

脚手架的演变

在前端研发活动中,脚手架负责项目的初始化工作,是后续研发活动的基础。一个典型的研发活动流程大概是这样:执行脚手架创建项目 -> 开发 -> 构建 -> 测试 -> 部署。

团队规模较小或者业务比较简单的时候,可能也用不上脚手架,比较常见的项目初始化方式是直接从一个已有的项目中拷贝一份出来,然后酌情删除业务相关代码,保留和修改基础代码。

如果业务发展比较快,隔段时间就需要新建一个项目,这种方式无疑比较繁琐,于是有了第二种方式。把上一种方式形成的模板代码上传到仓库中维护起来,需要新建项目时,将仓库代码 clone 出来,删除 .git 目录,重新上传到新项目的仓库。而且后续可以持续迭代这个模板仓库,维护性更好。

每次新建项目都需要走一遍如下过程:clone 代码 -> 删除 .git 目录 -> 关联并 push 到新仓库,略显繁琐,于是有了第三种方式。将这个过程封装成 CLI 命令,比如叫做 fe-cli ,每次需要新建项目只需要执行 fe-cli projectName 即可。得益于 Node.js 生态的繁荣,封装这个 CLI 并不难,只需综合运用好相关库即可(如 commander inquirer shelljs 等)。更进一步,可以在这个 CLI 里实现模板选择功能,这样的话,就可以支持不同类型的项目创建了。

脚手架的维护成本

用完即抛

一个显而易见的问题是,如果不是专门做基建的团队,花费时间和人力成本维护这样一个脚手架似乎有点得不偿失。脚手架的功能做得再丰富,交互性再好,也只是用来创建项目,生成一堆模板代码,项目创建好了就放置一边,等到下次创建才会再捡起来。

版本升级

还有一个比较麻烦的问题是,如果脚手架做了升级,除非在脚手架里面强制检测版本并要求用户升级,否则用户使用脚手架新建项目时,大概率可能用的是上次安装时的版本。辛苦更新的功能没法及时让用户使用上,非常尴尬。一个可能的解决办法是要求用户使用 npx 来代替 npm i -g ,这种方式无疑为使用增加了一点小成本。

工程方案 – 代码初始化

在 「Goofy Studio」(字节内部的一体化前端研发工作台,可以覆盖前端研发的所有活动,比如应用的创建,开发,构建,部署以及云 IDE 等) 里,我们给出的解决办法是「工程方案」。

「工程方案」不单纯是「脚手架」的升级版,而是一系列前端研发活动「最佳实践」的沉淀。工程方案包含多种配置,其中的「代码初始化配置」即涵盖了「脚手架」的功能。

我们提供了三种代码初始化方式:模板方式,云端 CLI 方式,webshell 方式。其实工程方案的代码初始化也是做了初始代码生成,新建仓库,push 代码等操作,与在本机执行脚手架并无大的不同。但是,工程方案的代码初始化完全是在云端容器执行的,最大程度的避免了本地环境差异造成的失败问题,且过程全自动,无需人工干预,大大节省时间。

更妙的是,工程方案的项目创建可以一次性将各种服务(比如构建服务节点,部署服务节点等)及发布流水线创建好,项目创建完成后即可进行发布,对于新人来说非常友好,对于资深的老人来说也非常省心。

由于本文主要阐述如何替换脚手架,因此工程方案的其他部分不多做介绍。

模板方式

这种方式是最简洁的,只需配置一个模板代码压缩包(tar)即可,代码初始化时会直接将该压缩包上传到新创建的仓库。

云端 CLI 方式

这种方式会在一个容器里执行设置好的命令以进行代码初始化,并将产物作为模板代码上传到新创建的仓库。这个过程各个环节均可配置,比如全局安装的包,执行的命令,产物的目录,需要忽略的文件及文件夹等。

下图是创建一个 Vue 项目的代码初始化配置。由于编译平台通过配置文件(scm_build.sh)来定义编译过程,因此我们提供了 @byted/studio-cli 来生成该配置文件。

上图使用-p default 生成了一个最简单的 Vue 项目,但是实际业务中可能需要开启内置的一些功能,比如 Vuex babel 等。因此我们提供了「schema 输入表单」来支持用户在初始化时向 CLI 传递数据。

为了演示 schema,我们再生成一个Gulu 工程 (Gulu 是内部使用的一种开发框架),并且提供模板选择功能,代码初始化部分配置如下图:

为了能渲染出上图中的模板选择下拉菜单,我们需要配置 schema:

{
  "schema": {
    "key""gulu",
    "isObject"true,
    "items": [
      {
        "key""template",
        "label""select template",
        "items": [
          {
            "key""http-server",
            "label""http-server"
          },
          {
            "key""http-server-ts",
            "label""http-server-ts"
          },
          {
            "key""thrift-server",
            "label""thrift-server"
          },
          {
            "key""thrift-server-ts",
            "label""thrift-server-ts"
          },
          {
            "key""plugin",
            "label""plugin"
          },
          {
            "key""plugin-ts",
            "label""plugin-ts"
          }
        ]
      }
    ]
  },
  "customUIConfig": {
    "template": {
      "ui""Select"
    }
  }
}

该部分的 schema 语法,采用了我们自己研发的一套动态表单方案。

webshell 方式

为了进一步降低代码初始化的配置门槛,我们也开发了 webshell 方式,即不需要配置任何 schema 表单,只需要配置 CLI 命令。执行代码初始化过程时,用户可以直接在页面的 webshell 上进行交互,完全模拟 CLI 在本机执行的过程。

webshell 方式也会作为 CLI 方式的兜底,即使 CLI 升级了,增加了一些问题,而 schema 没有及时更新,用户也可以在 webshell 里完成新增的问题交互,成功进行代码初始化。

小结

使用工程方案的代码初始化配置来代替脚手架,使得每次创建项目时使用的都是最新版的 CLI,而且每次都在一个全新的容器里进行,可最大程度提高代码生成成功率。

工程方案市场

前面说到「工程方案」是前端研发活动「最佳实践」的沉淀,因此我们做了「工程方案市场」,将「最佳实践」以实体的方式提供出来,任何人可以直接使用。

将团队定制的工程方案放到工程方案市场里,一方面方便团队的业务开发,维持技术的统一性,另一方面也可以向外输出影响力。


来源: 字节前端 ByteFE