- 规范保障 每个团队都会根据实践经验,总结出一套自己的规范(项目规范和流程规范)。让这一套规范在落地到实际的开发中时,除了人为的约束,更多的应该是通过工具约束。工程化就是把团队的经验沉淀到脚手架和开发套件中,让新项目或新成员可以复用这些经验。
- 提效 一个好的工程化方案,是可以提升开发效率的,这个提效包括初始化项目,完备项目的dev环境,数据mock,build打包等一系列流程,既要让项目“搭建-开发-部署”更快捷高效,也要方便项目的后期维护和迭代。
- 减少人力 在开发过程中可能会遇到一些重复人力的工作。例如A、B两个系统有一个相似的列表页,这个列表页不能作为组件抽离,但是又在多处能用到,这部分资源(代码模板)复用急需一个中间媒介来完成。 假如资源/项目需要升级了,大多情况是资源开发者出一个升级文档,然后升级的人按照文档一步步修改。这是很重复的一份工作,因为假如你手上有十个项目,你就需要把相同的事情做十遍,这一步重复的工作我们希望可以通过工具来完成。
-
渐进式(技术演化能力)易于迭代
-
扩展性(可伸缩、可插拔)易于部门共建
-
易用性(贴合实际)易落地
-
数据统计与分析
基于以上的目标,下面来看一下整个工程化的方案设计。
首先,介绍整个方案的架构图:
2.1.1 底层依赖
最底层依赖了规范、webpack、schematics、node、eslint,它是上次架构的基石。- 规范这里包括了项目规范和流程规范,是整套方案需要遵守的约定; 因为这套规范是根据大量的实际业务总结出来的,所以它是贴合业务场景,便于整体方案落地的。
- schematics 引入主要是为了解决上面说到的资源相关的问题,后面会详细讲到。
2.1.2 插件封装层
这一层主要是对上层需要实现的功能做一个划分,然后通过插件的形式实现。例如:- 将一系列模板抽离作为一个集合,然后将项目初始化时需要做的模板选择和模板处理放到 init 插件中完成,不同团队可以根据规范自定义插件;
- 开发编译阶段需要的 webpack 和 server、build 脚本放在 @sharkr/scripts 插件中完成,不同团队可以根据规范自定义插件;
- 前面说到的资源复用和资源升级问题,统称为文件处理相关,@sharkr/schematics-cli 插件提供这个能力;
- @sharkr/eslint-config-react 插件提供 eslint 检查;
- 还有一部分公共能力封装成 util 插件,方便共享。
- init 完成项目初始化
- dev 可以使开发者快速的进入开发
- add 可以给项目增加一个资源
- generate 可以执行资源里定义的命令
- update 帮助快速升级资源
- lint 编码规范校验
- test 对开发过程中的代码做一个测试
- build 在CI阶段可以帮助完成编译打包
- 用户执行 sr init myapp,调用 @sharkr/cli
- @sharkr/cli 检查 init 插件版本
- 发现版本不是最新的,提示用户 update @sharkr/cli
- 用户全局 update @sharkr/cli
- 再次执行 sr init myapp, 调用 @sharkr/cli
- @sharkr/cli 调用最新的 init 处理
npx 是 npm5.2 版本中新增的命令,它能临时下载一个模块并且运行它,运行之后再删除这个模块
- 用户执行 sr init myapp,调用 @sharkr/cli
- @sharkr/cli 使用 npx 调用最新的 init 插件处理
完成项目初始化进入开发阶段,这个阶段应该是关注业务本身、减少重复工作、高效快速的。
2.3.1 dev 环境 开始项目开发遇到的第一个问题就是 dev 环境。需要 webpack 配置编译代码、需要一个本地 server、需要一个数据转发、需要 eslint 配置规范编码等。 这一部分可以通过 @sharkr/scripts 提供 webpack 配置和 server 脚本,在模板里集成调用,用 koa 起一个本地服务,koa 中间件完成转发等。@sharkr/eslint-config-react 定义编码规范。在这个环节规范了流程和配置,有效的保障项目质量。 有了一个完备的 dev 环境,再来看一下前面说到的资源复用和资源/项目升级。 2.3.2 资源复用和资源/项目升级 资源复用 简单把资源分为两类,一类是有固定输入输出,可抽离的,例如时间控件,下拉列表等;还有一类是无固定输入输出,不可抽离,但是又具有某些共性的,例如B端常见的列表页、详情页,这一部分资源没有一个很好的复用方式。 对于第一类资源,可以采用封装组件的形式完成资源共享:对于第二类资源,以前的做法基本是 Ctrl+c、Ctrl+v 来复用,这种做法不够高级,还效率不高,所以在 cli 中提供了另外一种做法,那就是将代码模板抽离到一个 schematic 包里,然后通过 @sharkr/cli 来安装这个包,并且执行里面的 schematic。
资源/项目升级
同样的,假如项目或者是资源需要升级,就需要在项目中升级依赖,可能还需要修改配置、甚至调整目录结构、修改api调用等。这种升级以前的做法是,出一份升级文档,升级者按照文档一步步修改项目完成升级。假如有几十个项目,就需要几十个人做相同的事几十遍,这无疑是一个大的人力消耗,作为一个提效工具,就是需要将这部分重复的工作通过代码完成。
- 把升级文档里做的事情编写成 schematic 包
- 通过 @sharkr/cli 来安装这个包,并且执行里面的 schematic
schematics 是 ngCli 团队开发的一个强大和通用的工作流程工具,开发者可以将变换应用于项目中,例如:创建新组件、添加配置项、修改现有项目,或者更新你的代码来修复更新依赖时带来的 break change。
原理schematics 如它名字一样,可以理解为一个描述了具体操作的原理图。
schematics 的输入是一个树,包含一个基础区域(一组已经存在的文件)和一个临时区域(要应用于基础区域的更改列表)),schemtics 描述了对 Tree 的修改,并将这些修改合并到临时区域的更改列表中,再往外输出一个新的 Tree。
在整个操作完结,并得到确认后,链条中所有描述的修改才会真正被应用。
更多schematics知识(https://angular.io/guide/schematics)
优势和常规的js脚本工具相比,它的优势在哪呢?
-
开发便捷
提供了丰富而强大的通用能力,帮助开发者快速开发:在 code generate 领域,可以通过使用其模板能力,构建各种类型的动态场景代码模板,快速生成代码。同时还提供了丰富的 util,提供包括 ast、git 初始化、TslintFixTask tslint 处理等能力。
-
易于调试
schmatics 由于其虚拟树的设计,在开发阶段支持干运行,并不会对文件系统执行任何直接操作,方便开发者在项目中进行调试,安全无污染。
-
可扩展性和可重用性
从其原理可以看出,schmatics 的整体设计,遵循了函数式范式,schematics 不会产生副作用(副作用只会被记录在缓存区中),具备原子性。schematics 可以自由 Compose 成新的 schematics。
-
测试友好
schmatics 提供了完备的测试支持库,测试用例书写没有障碍。
schematics 封装
既然 schematics 处理文件很友好,而且刚好能解决文件处理问题,于是我们就引入了 schematics 完成文件处理,并对它做了一层封装。-
最底层主要依赖 @angular-devkit/schematics 和 @angular-devkit/core 提供 schematics 基础能力;
-
将公共能力提取到 @schematics/util 方便开发调用;
-
提供 schematics 开发模板,方便开发新建 schematics 包;封装 schematics 的 cli,也就是说它也可以单独调用命令;
-
资源(通用资源、项目改造资源、模板升级资源等)会做一些整合,这些资源集合将作为物料维护在物料海,将来会跟我们正在开发的物料平台对接;
-
向上暴露所有的命令,最终在 @sharkr/cli 作为统一出口。
下面再来看下,开发和使用一个 schematics 包需要做点什么呢?
首先,对于开发者来说,需要做以下三步:
-
根据 schematics 规范开发一个 schematics 包
-
定义配置项(可选)
-
定义 schema 命令
其次,对于用户来说,需要做以下三步:
-
使用 @sharkr/cli 调用 schematics 包
-
输入配置(可选)
-
完成项目修改
那么 @sharkr/cli 做了什么了?
-
@sharkr/cli 调用 @sharkr/schematics 插件
-
schematics 插件解析出自定义配置项,生成用户会话
-
根据用户会话拿到 option,传入 option 调用 Rule 函数
-
修改文件放到暂存区
-
确认修改后更新物理文件
这里 Rule 函数是需要开发者实现的,任何你想写成文档的都能通过代码方式写在这个 Rule 函数里。
schematics 实践 下面来看一个实际的例子:前段时间我们的项目都需要完成服务上云,为了实现上云,需要调整下CI脚本,还要往项目里放一些环境配置文件,涉及到多处文件修改和增加,所以我们写了一个 @sharkr/ng-cloud-add 的 schematics 包达到快速改造项目的目的。以下是效果:
核心代码写起来跟写文档类似:
以上就讲完了在开发/迭代过程中遇到的问题和解决方案,最后再看一下CICD阶段做了什么。
2.4 CI这部分跟 dev 环境类似,也需要提供 webpack 配置、build 脚本、还约束了 build 打包后的目录规范、配置部署相关文件。
价值与后续计划 价值通过介绍以上的一些方案设计,可以发现这套工具可以让开发更专注业务本身,初始化项目之后就可以直接进入开发;重复的操作可以通过 schematics 完成,省去重复的人力成本;项目/资源升级可以更加快速推进;规范和文档沉淀到工具中供使用,非常有利于规范的遵守。
后续计划接下来长远的规划将会从以下两点展开:
- 与资源平台结合。目前放在 schematics 包里的资源没有一个很好的展示平台,后续将会对接物料平台,让资源更容易被使用。
- vscode 可视化扩展能力。为了让开发在开发过程中更加快捷高效,后续会结合 vscode 的插件能力,让添加资源更容易。
- 开发规范的落地依赖模板收敛项目规范,cli 工具收敛流程规范的方式,并在初始化项目时将模板应用于实际项目场景。
- cli 工具的扩展依赖于插件式,对于自定义的部分提供相应插件即可扩展,而插件的更新依赖 npx 调用的方式,解决用户需要频繁更新问题。
- 方便快速初始化项目,提供完备的 dev 环境和 build 脚本等提升了开发效率。
- 资源复用和资源/项目升级统称为文件处理,这部分借用了 angular 里的 schematics 功能来完成。在这部分还讲了什么是 schematics 以及它在 cli 里做了什么。