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<Tree> | 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", `<h1>Hello ${options.name} 👋</h1>`);
    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学习之旅的开端。
更多资源请浏览:

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,932评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,554评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,894评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,442评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,347评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,899评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,325评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,980评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,196评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,163评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,085评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,826评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,389评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,501评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,753评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,171评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,616评论 2 339

推荐阅读更多精彩内容