[Angular Schematics] NX기반 Custom Schematic 개발하기 - 1
Angular에서 schematic은 복잡한 로직을 지원하는 템플릿 기반의 코드 생성기이다. @angular/cli에서 코드 생성은 schematics를 사용하는 것이다. 해당 패키지는 @schematics/angular 이다. 본글에서는 나만의 schematic을 만들어 본다. 하기 문서를 참조하여 NX 기반으로 개발한다.
https://medium.com/@tomastrajan/total-guide-to-custom-angular-schematics-5c50cf90cdb4
Schematic 생성
NX환경이 아니라면 @angular-devkit/schematics-cli 를 글로벌로 설치해서 schematics 명령을 사용해 초기 schematic파일을 자동 생성할 수 있다. 그러나 NX를 사용하면 @angular-devkit/schematics-cli설치 없이 nx명령으로 초기 파일을 생성할 수 있다. NX의 schematics을 사용하겠다는 정의는 루트의 angular.json에 정의되어 있다.
...
"schematics": {
"@nrwl/angular:application": {
"unitTestRunner": "jest",
"e2eTestRunner": "cypress"
},
"@nrwl/angular:library": {
"unitTestRunner": "jest"
}
},
...
명령어 예
//schematic-cli 설치
$ npm install -g @angular-devkit/schematics-cli
//schematics 명령 사용 경우
$ schematics blank hello
//NX 환경일 경우
$ nx g workspace-schematic hello
CREATE tools/schematics/hello/index.ts (250 bytes)
CREATE tools/schematics/hello/schema.json (348 bytes)
nx 명령을 생성된 schematic 파일은 tools/hello 폴더 밑에 존재한다. schema.json은 hello schematic의 정의 파일이고, index.ts가 동작하는 시작 파일이다.
Schematic 키워드
- Tree: virtual file system을 표현한다. base 라는 이미 존재하는 파일 묶음과 staging area 라는 base에서 변경될 것들 목록으로 구성된다. base 는 변경할 수 없고, staging area 만 변경가능 하다.
- Rule: Tree를 받아서 변경점을 적용하고 새로운 Tree를 반환하는 함수이다. 메인 파일인 index.ts에 해당 함수를 정의한다.
- Action: Action을 변환(Transformation)으로 표현되고, action 타입은 Create, Rename, Overwrite, Delete 4가지 유형이 있다.
- 참조 원문
실제 사용자 정의 작업을 해야하는 Rule의 정의이다.
export declare type Rule = (tree: Tree, context: SchematicContext) => Tree | Observable<Tree> | Rule | Promise<void> | Promise<Rule> | void;
모든 Schematic은 context안에서 구동되어야 하고, SchematicContext 객체로 표현된다. nx가 아닌 schematics 명령으로 생성된 index.ts 의 코드를 보자.
- hello함수는 RuleFactory로써 Rule을 반환하는 고차함수(a higher-order function)를 반환한다.
- hello함수안에서 나의 template이 어떻게 합쳐지고, 변경되어 지는 것인지 정의한다.
//schematic 명령으로 생성된 index.ts 내역
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
// You don't have to export the function as default. You can also have more than one rule factory
// per file.
export function hello(_options: any): Rule {
return (tree: Tree, _context: SchematicContext) => {
return tree;
};
}
nx로 생성된 schematic 의 index.ts는 약간 틀린 구조이다.
- default함수로 RuleFactory를 정의한다.
- Rule을 반환한다.
import { chain, externalSchematic, Rule } from '@angular-devkit/schematics';
export default function (schema: any): Rule {
return chain([
externalSchematic('@nrwl/workspace', 'lib', {
name: schema.name,
}),
]);
}
Schematic 옵션 설정
- nx로 생성했을 경우: schema.json 파일에 옵션을 설정한다.
- schema.json의 properties 는 Schematic 수행시 prompt 로 작동하여 사용자 입력값을 처리한다.
- properties안에 사용자로 부터 입력받고자하는 옵션을 설정한다. 입력받을 수 있는 옵션은 schema.json에 정의되어 있다.
- schema.json 전체 명세서
//nx 명령으로 생성된 schema.json 내역
{
"$schema": "http://json-schema.org/schema",
"id": "hello",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Library name",
"$default": {
"$source": "argv",
"index": 0
}
}
},
"required": ["name"]
}
옵션의 Input "type"
- confirmation: boolean 옵션
- input: text 또는 number 옵션
- list: 미리 정의한 목록을 선택
"style"을 정의한 예
//schema.json 예
"style": {
"description": "The file extension or preprocessor to use for style files.",
"type": "string",
"default": "css",
"enum": [
"css",
"scss",
"sass",
"less",
"styl"
],
"x-prompt": {
"message": "Which stylesheet format would you like to use?",
"type": "list",
"items": [
{ "value": "css", "label": "CSS" },
{ "value": "scss", "label": "SCSS [ https://sass-lang.com/documentation/syntax#scss ]" },
{ "value": "sass", "label": "Sass [ https://sass-lang.com/documentation/syntax#the-indented-syntax ]" },
{ "value": "less", "label": "Less [ http://lesscss.org ]" },
{ "value": "styl", "label": "Stylus [ http://stylus-lang.com ]" }
]
},
},
x-prompt 필드를 통해 긴 입력 문구 조합이 가능하다.
//x-prompt schema
{
"oneOf": [
{ "type": "string" },
{
"type": "object",
"properties": {
"type": { "type": "string" },
"message": { "type": "string" },
"items": {
"type": "array",
"items": {
"oneOf": [
{ "type": "string" },
{
"type": "object",
"properties": {
"label": { "type": "string" },
"value": { }
},
"required": [ "value" ]
}
]
}
}
},
"required": [ "message" ]
}
]
}
Schematic 실행
Schematics CLI로 생성했을 경우
- index.ts를 컴파일한다.
- 명령어: schematics <path-to-schematics-project>:<schematics-name> --<required-option>=<value>
//schematics 으로 생성한 폴더로 이동후 컴파일 수행
$ cd hello
$ npm run build
//schematics 수행
$ schematics .:hello
Nothing to be done.
nx 명령으로 생성했을 경우
- 명령어: npm run workspace-schematic <customized schematic name> <option>
$ npm run workspace-schematic hello hi
> micro-demo@0.0.0 workspace-schematic /Users/dowonyun/mobicon/projects/bistel/src/2019/micro-demo
> nx workspace-schematic "hello" "hi"
> NX Executing your local schematic: hello
CREATE libs/hi/tslint.json (91 bytes)
CREATE libs/hi/README.md (158 bytes)
CREATE libs/hi/tsconfig.json (135 bytes)
CREATE libs/hi/tsconfig.lib.json (190 bytes)
CREATE libs/hi/src/index.ts (26 bytes)
CREATE libs/hi/src/lib/hi.ts (0 bytes)
CREATE libs/hi/jest.config.js (246 bytes)
CREATE libs/hi/tsconfig.spec.json (269 bytes)
UPDATE tsconfig.json (731 bytes)
UPDATE angular.json (16683 bytes)
참조
Angular Schematic 개념: https://angular.io/guide/schematics