Angular Schematics教程

该文章翻译自链接。权当存档备案

什么是Schematics?

Schematics是改变现存文件系统的生成器。有了Schematics我们可以:

  • 创建文件
  • 重构现存文件,或者
  • 到处移动文件

Schematics能做什么?

总体上,Schematics可以:

  • 为Angular工程添加库
  • 升级Angular工程中的库
  • 生成代码

在你自己的工程或者在你所在的组织中使用Schematics是具有无限可能的。下面一些例子展现了你或者你的组织或如何从创建一个schematics collection中获益:

  • 在应用中生成通用UI模板
  • 使用预先定义的模板或布局生成组织指定的组件
  • 强制使用组织内架构

Angular指定?

现在是,Schematics是Angular生态圈的一部分

CLI集成?

是的,schematics与Angular CLI紧密集成。你可以在下列的CLI命令中使用schematics:

  • ng add
  • ng generate
  • ng update

什么是Collection?

Collection是一系列的schematic。我们会在工程中collection.json中为每个schematic定义元数据。

安装

首先,使用npm或者yarn安装schematics的CLI:

$ npm install -g @angular-devkit/schematics-cli
$ yarn add -g @angular-devkit/schematics-cli

起步

起步时我推荐检验下例子schematics并通读代码和相关注释。我们可以使用下列语句生成例子schematics:

$ schematics schematic --name demo

Hello World Demo

这是github链接

Hello World

简单的"Hello World" schematic有助于我们起步。使用schematics CLI创建一个新的schematics的空工程:

$ schematics black --name=hello-world
$ cd hello-world

打开src/collection.json:

{
  "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
  "schematics": {
    "hello-world": {
      "description": "A blank schematic.",
      "factory": "./hello-world/index#helloWorld"
    }
  }
}

回看一下collection.json结构:

  • $schema属性指明了检验的schema
  • schematics属性是一个对象,里面每一个键都是schematic的name
  • 每个schematic都有description属性来描述这个schematic
  • 每个schematic也有一个factory属性,它是一个string,指明了我们的schematic的入口点的文件位置,之后是一个#,然后是要调用的函数。在此处我们会调用在hello-world/index.js文件中的helloWorld()函数

我们也可以指明一些附加属性:

  • 可选的aliases属性是一个数组,我们能用来指定我们的schematic的一个或者多个别名。举个例子,在Angular CLI中"generate" schematic的别名是"g"。这允许我们通过$ ng g调用generate命令
  • 可选的schema属性可用来指明每个单独schematic的schema和所有的可用的命令行选项

另一个值得注意的是在工程中的package.json文件包含一个新的schematic属性指向src/collections.json文件:

{
  "name": "hello-world",
  "version": "0.0.0",
  "description": "A blank schematics",
  "scripts": {
    "build": "tsc -p tsconfig.json",
    "test": "npm run build && jasmine src/**/*_spec.js"
  },
  "keywords": [
    "schematics"
  ],
  "author": "",
  "license": "MIT",
  "schematics": "./src/collection.json",
  "dependencies": {
    "@angular-devkit/core": "^7.0.2",
    "@angular-devkit/schematics": "^7.0.2",
    "@types/jasmine": "^2.6.0",
    "@types/node": "^8.0.31",
    "jasmine": "^2.8.0",
    "typescript": "^2.5.2"
  }
}

入口函数

打开src/hello-world/index.ts文件,看看内容:

import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';

export function helloWorld(options: any): Rule {
  return (tree: Tree, _context: SchematicContext) => {
    return tree;
  };
}
  • 我们export了会作为"entry function"调用的helloWorld函数
  • 函数接受一个options参数,它是命令行参数的键值对对象
  • 这个函数是一个高阶函数,接受或者返回一个函数引用。此处,这个函数返回一个接受TreeSchmaticsContext对象的函数

什么是Tree?

文档中指出,Tree是:

变化的待命区域,包含源文件系统和一系列应用到其上面的变化。

我们能使用tree完成这些事情:

  • read(path: string): Buffer | null: 读取指定的路径
  • exists(path: string): boolean: 确定路径是否存在
  • create(path: string, content: Buffer | string): void: 在指定路径使用指定内容创建新文件
  • beginUpdate(path: string): UpdateRecorder: 为在指定路径的文件返回一个新的UpdateRecorder实例
  • commitUpdate(record: UpdateRecorder): void: 提交UpdateRecorder中的动作

我们会在这个文章之后解说UpdateRecorder

什么是Rule?

Rule是一个根据SchematicContext为一个Tree应用动作的函数:

declare type Rule = 
 (tree: Tree, context: SchematicContext) => 
 Tree | Observable | Rule | void;

在上面的hello world例子代码中,helloWorld()入口函数返回了一个Rule

构建和执行

继续往前走,我们来构建和执行我们的schematic:

$ yarn build
$ schematics .:hello-world --foo=bar

需要注意的一个事:

  • 我们使用schematics CLI,而非Angular CLI来执行schematic
  • 第一个选项是指定collection名,在这个例子中,我们指向了当前文件.作为collection
  • collection名是可选的。如果我们忽略collection名字内建collection会被使用。我们在之前执行"blank"schematic时就使用了内建collection
  • 如果我们指定collection名,我们使用冒号来分开schematic名字后面的collection名
  • 在这个例子中我们执行了"hello-world" schematic
  • 最后我们指明了我们schematic的"foo"选项,值为"bar"

我们在从helloWorld函数中返回的函数里加一个log语句:

export function helloWorld(options: any): Rule {
  return (tree: Tree, _context: SchematicContext) => {
    console.log(options);
    return tree;
  };
}

构建并执行这个schematic,你应该能看到你在schematic中指定的选项的日志:

$ yarn build
$ schematics .:hello-world --foo=bar
{ foo: 'bar' }
Nothing to be done.

生成Hello World模板

我们的schematic现在只能输出用户指定的选项。我们来升级下我们的Rule函数来使用tree.create()函数来新建一个新文件:

export function helloWorld(options: any): Rule {
  return (tree: Tree, _context: SchematicContext) => {
    tree.create("hello-world.html", `

Hello ${options.name}

`); return tree; }; }

正如我们之前学到的,create()方法接收我们要新建的文件的path和文件的content。在这个例子中,我们简单的使用用户指定的值name和前面的"Hello"字符串来填充hello-world.html模板。

当我们构建并执行升级过的schematic我们应该看到:

$ yarn build
$ schematics .:hello-world --name="Angular Community" --dry-run
CREATE /hello-world.html (37 bytes)

注意:

  • 在执行时指明了name选项
  • 指明了dry-run选项来避免实际的文件创建。移除dry-run选项会在你当前工作目录中创建hello-world.html模板

单元测试

Angular schematics包含了一个SchematicTestRunner,用来构建单元测试套件来保证你schematics collection的质量。

让我们来测试一下我们新建的hello-world schematics:

const collectionPath = path.join(__dirname, "../collection.json");

describe("hello-world", () => {
 it("works", () => {
   const runner = new SchematicTestRunner("schematics", collectionPath);
   const tree = runner.runSchematic("hello-world", {}, Tree.empty());

   expect(tree.files.length).toEqual(1);
 });
});
  • 测试使用Jasmine执行
  • 我们new了个SchematicsTestRunner类,指定了collectionNamecollectionPath
  • 使用测试运行程序我们调用了runSchematic(),指定了schematicName,选项对象和源Tree
  • 最后我们声称tree的文件数已经增长到了1

结论

我希望这是你的Angular Schematics学习之旅的开端。
更多资源请浏览:

  • Getting Started with Schematics
  • Schematics book by Manfred Steyer (免费的电子书,感觉很全)

你可能感兴趣的:(Angular Schematics教程)