Schematics 是前端开发工做流工具,例如:建立一个组件、变动配置项至当前项目。而且不限制任何语言环境;虽然如此,但 Schematics 目前依然只能依赖 Angular Cli 来运行相应的命令行。html
本文是在重构 ng-alain schematics 时阅读 @angular-devkit
源码的一些记录;而关于 Schematics 的运用在知乎上有好几篇不错的文章,我将尽量跳开一些没必要要的重复性工做,建议阅读本文时能够同下列文章一块儿阅读。前端
Schematics 一共包含四个指令:git
add
添加一个 Library 至项目new
建立一个新 Angular 项目generate
基于 Schematics 建立或修改文件update
更新应用程序或依赖项其实除了 add
会事先执行一次 npm i
(取决于 angular.json
的 cli/packageManager
配置值,默认:npm
)指令之外,其余指令实际上都是基于 Schematics 建立或修改文件。github
generate
指令会更纯粹,须要你手动指定 Schematic 名称,例如:ng g class <ClassName>
。其余三个指令是对其进一步简化,像 ng add
实际至关于 ng g ng-add
这里的 ng-add
是固定名称,若你但愿建立一个支持 ng add
那么你就必须有一个 ng-add
的 Schematic。typescript
Schematics 执行核心的本质就是在维护一个很是大的 Observable 数据流,这里的数据就是文件树。npm
核心的主轴是执行一个 Schematics 时会在开始时构建一个虚拟文件系统 virtual-fs 就像 Rxjs 的 Observable
,后续的操做符都是对文件系统的变动动做,最后将虚拟文件系统的内容影射至物理文件中。json
一个 Schematics 能够包含多个不一样的指令,例如默认 Angular Schematics 有很是多咱们熟悉的 module
、component
等,而管理这些指令是经过 collection.json 配置项。工具
Schematics 建立完虚拟文件系统环境后,紧跟着依 collection.json 构建 Collection 对象,再根据指令中的名称建立 Schematic 对象;而且调用并运行 Schematic Name 所对应目录名下 index.ts
文件,例如一个 Schematic 完整的代码结构:测试
function rule1() { return (host: Tree, context: SchematicContext) => { // doing }; } export default function(options: ApplicationOptions): Rule { return (host: Tree, context: SchematicContext) => { return chain([ rule1(), rule1() ]); } }
最终返回一个 Rule
类型,其本质是:命令行
(tree: Tree, context: SchematicContext) => Tree | Observable<Tree> | Rule | void
若返回的是一个 Observable
类型时意味者这里的空间变得无限大:
function rule1() { return (host: Tree, context: SchematicContext) => { return of(host); }; }
好比构建本身的远程代码片段库。
Schematics 除了运行 Schematic 指令之外,还须要一些对项目进行额外操做,例如:安装Node依赖包、初始化 Git 等。其实运行 Schematic 指令自己也是一种任务。这些任务是经过 SchematicContext
进行管理。
例如咱们但愿在执行一个 Schematic 指令后调用一次 Node 依赖包的安装,只须要调用内置的 NodePackageInstallTask
任务:
(host: Tree, context: SchematicContext) => { context.addTask(new NodePackageInstallTask()); }
angular.json 与 Schematic 有着很是密切的关系,大多数须要经过 angular.json 配置信息来获取目录路径、默认配置项等信息。特别是当编写 Schematic 时老是须要考虑多项目的状况,所以绝大多数都须要依赖 angular.json 来确认具体项目名及路径信息。
每个 Schematic 指令都有相应的参数信息,这些参数信息也能够直接被映射在 angular.json 上面并当成默认参数值:
{ "schematics": { "ng-alain:list": { "spec": false }, "@schematics/angular:component": { "spec": false } } }
经过 ng g ng-alain:module <name>
(或 ng g component <name>
)生成时将忽略测试文件;固然对于这些默认参数的转化都是 Schematics 内自动完成。
以上是一些简单总结,Schematics 可玩性很是强,它是运行在一个 Node 容器内,所以可使用当下全部 Node 类库。
而 Schematics 的操做除了文件之外,也会对文件内容进行修改,这一些也颇有意思。像 ts 文件能够利用 typescript 类库来获取或调整 ts 文件内容某个变量名或值。而 html 文件能够利用 parse5 来解析并修改,绝大多数文件类型均可以找到相对应的现有类库来支持。
Schematics 只是 @angular-devkit
中的一小部分而已,还包括:Architect 用于改变 Angular cli 的运行机制,虽然本质上是在改变 Webpack 配置文件,但谁叫 Webpack 有着无限可能呢。
原先@angular-devkit
是做为一个独立的仓储位于 @angular/devkit,然而不久前被合并入@angular-cli
里。
(完)