之前的文章介紹了 Schematics,現在就來自己建立一個 Schematics collection,我們希望建立出來的 collection 可以保留原有 Angular CLI 的功能,並擴充自己想要的樣板
基本設定
-
先建立一個資料夾
-
新增
package.json
檔案,請依基本的npm
專案方式設定,新增下列設定1
"schematics": "./collection.json",
-
建立
collection.json
檔案,並新增以下內容1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48{
"schematics": {
"class": {
"aliases": ["cl"],
"extends": "@schematics/angular:class"
},
"component": {
"aliases": ["c"],
"extends": "@schematics/angular:component"
},
"directive": {
"aliases": ["d"],
"extends": "@schematics/angular:directive"
},
"enum": {
"aliases": ["e"],
"extends": "@schematics/angular:enum"
},
"guard": {
"aliases": ["g"],
"extends": "@schematics/angular:guard"
},
"interface": {
"aliases": ["i"],
"extends": "@schematics/angular:interface"
},
"module": {
"aliases": ["m"],
"extends": "@schematics/angular:module"
},
"pipe": {
"aliases": ["p"],
"extends": "@schematics/angular:pipe"
},
"service": {
"aliases": ["s"],
"extends": "@schematics/angular:service"
}
}
}
到這個步驟時,已經將 Angular CLI 既有的功能移植到我們的 collections 內了。接下來就將目前的檔案簽入到 GitHub 上,npm 可以設定 devDependencies
程式碼來源為 GitHub Repo,指定的方式是
1 | "<<package name>>": "<<GitHub account>>/<<repo name>>", |
在新的或是既有的 Angular 專案,只要 Angular CLI 版本是在 1.4 版以上,都可以設定 collection
,可修改 .angular-cli.json
檔案,設定方式如下
1 | "defaults": { |
當完成以上步驟時,我們還是可以正常的使用 Angular CLI 的指令,但是觸發的指令清單是根據我們版本的 collection,不在是預設的範本了,換句話說,我們可以更換指令,例如說 ng g component 的縮寫,希望從 c
改成 comp
,這是可行的,只要修改 collection.json
對應的 alias
即可
1 | // 修改前 |
自訂範本
上一段我們完成沿用 Angular CLI 所提供的功能,現在要來製作自己的樣板了,基本的操作步驟是
-
在
collection.json
內新增一個指令區塊1
2
3
4
5"feature":{
"factory": "./src/feature",
"schema": "./src/feature/schema.json",
"description": "Create a feature module"
} -
建立
feature
資料夾,並在資料夾內新增index.ts
和schema.json
兩個檔案 -
schema.json
內可設定建立 feature 時所需的參數,相對的也要建立schema.d.ts
檔案1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32{
"$schema": "http://json-schema.org/schema",
"id": "SchematicsSchematicSchema",
"title": "Schematic Options Schema",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name for the new feature module."
},
"sourceDir": {
"type": "string",
"format": "path",
"description": "The path of the source directory.",
"default": "src",
"visible": false
},
"prefix": {
"type": "string",
"format": "html-selector",
"description": "The prefix to apply to generated selectors.",
"alias": "p"
},
"selector": {
"type": "string",
"format": "html-selector",
"description": "The selector to use for the component."
}
},
"required": ["name"]
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16export interface Schema {
sourceDir?: string;
/**
* The name for the new feature module.
*/
name: string;
/**
* The prefix to apply to generated selectors.
*/
prefix?: string;
/**
* The selector to use for the component.
*/
selector?: string;
} -
index.ts
內容1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45import {
Rule,
SchematicsException,
apply,
Tree,
SchematicContext,
branchAndMerge,
chain,
mergeWith,
move,
template,
url
} from '@angular-devkit/schematics';
import * as stringUtils from '../strings';
import { Schema as FeatureOptions } from './schema';
function buildSelector(options: FeatureOptions) {
let selector = stringUtils.dasherize(options.name);
if (options.prefix) {
selector = `${options.prefix}-${selector}`;
}
return selector;
}
export default function(options: FeatureOptions): Rule {
options.selector = options.selector || buildSelector(options);
const sourceDir = options.sourceDir;
if (!sourceDir) {
throw new SchematicsException(`sourceDir option is required.`);
}
return (host: Tree, context: SchematicContext) => {
const templateSource = apply(url('./files'), [
template({
...stringUtils,
...options
}),
move(sourceDir)
]);
return chain([branchAndMerge(chain([mergeWith(templateSource)]))])(host, context);
};
} -
相關的程式碼請參閱 GitHub Repo