Angular/Concept

[Angular Schematics] NX기반 Custom Schematic 개발하기 - 1

Peter Note 2020. 5. 22. 17:15

Angular에서 schematic은 복잡한 로직을 지원하는 템플릿 기반의 코드 생성기이다. @angular/cli에서 코드 생성은 schematics를 사용하는 것이다. 해당 패키지는 @schematics/angular 이다. 본글에서는 나만의 schematic을 만들어 본다. 하기 문서를 참조하여 NX 기반으로 개발한다.

 

https://medium.com/@tomastrajan/total-guide-to-custom-angular-schematics-5c50cf90cdb4

 

Total Guide To Custom Angular Schematics

Schematics are great! They enable us to achieve more in shorter amount of time! But most importantly, we can think less about mundane…

medium.com

 

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: 미리 정의한 목록을 선택

schema.json에 정의하는 type

"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

 

Angular

 

angular.io

스키마 명세: https://github.com/angular/angular-cli/blob/7.0.x/packages/schematics/angular/application/schema.json

 

angular/angular-cli

CLI tool for Angular. Contribute to angular/angular-cli development by creating an account on GitHub.

github.com