블로그 이미지
윤영식
Full Stacker, Application Architecter, KnowHow Dispenser and Bike Rider

Publication

Category

Recent Post

2019. 1. 9. 18:26 Angular/Architecture

Nx Workspace와 NgRx/Platform을 연결한 boilerplate를 만들어 본다. 


  - Nx Workspace 생성하기 

  - NgRx 개념이해  및 사용예 만들기

  - 다음 3가지 문서와 동영상을 참조한다.

    + Nx Workspace 무료 동강 수강

    + Nx Workspace 메뉴얼

    + NgRx와 Nx Workshop 강좌

    + State Management Type 정리

    + Nx Workspace 기반 예제소스




Nx Workspace 생성


하나의 저장소에 여러 애플리케이션을 개발할 수 있는 workspace를 최초 한번 생성한다.  

  - 현재 최신 버전의 스케매티과 CLI를 설치한다. v7.* 이다.

  - workspace 생성시 npmScope를 설정하여 workspace의 공통 library를 import할 때 prefix로 사용된다. 예로 @jm/<library name> 식이다. 

     또한 컴폰너트 selector의 prefix로 사용된다.

  - workspace 생성시 옵션은 scss, npm (또는 yarn)을 선택한다.

$ npm i -g @nrwl/schematics @angular/cli


// create -react-app과 유사, 첫번째 인자는 workspace 명칭이다. 

$ create-nx-workspace  jamong  --npm-scope=jm


nx workspace에서 사용(2019.1.8)기준 Redux 패턴의 구현체인 ngrx/platform 버전이 v6.*으로 설정되어 있기에 v7.0.0으로 변경한다. 

  - <workspace>/package.json에서 @ngrx/xxxx 의 버전을 ^7.0.0 으로 설정한다. 

$ cd jamong

$ vi package.json


// 수정후 다시 install 한다.

$ npm i


다음으로 샘플 애플리케이션을 생성한다. 

  - g는 generate, app은 application 이다. 

  - dashboard 명칭의 애플리케이션을 생성한다.

  - routing, unit test - jest, e2e - cypress, linting등을 선택한다.

$ ng g app dashboard

또는

$ ng generate application dashboard


// 작동여부 확인

$ npm start --project=dashboard


다음으로 애플리케이션안에 component를 자동생성할 때 옵션을 미리 설정해 놓는다. angular workspace의 schematics 설정 목록을 참조한다.

  - <workspace>/angular.json 파일의 dashboard 애플리케이션에 하기 항목을 추가한다. 

  - OnPush, viewEncapsulation 적용

생성시 적용될 수 있도록 맨 하단에도 동일한 설정을 한다. 

  "schematics": {

    "@nrwl/schematics:application": {

      "style": "scss",

      "changeDetection": "OnPush",

      "viewEncapsulation": "None"

    },

    "@nrwl/schematics:library": {

      "style": "scss",

      "changeDetection": "OnPush",

      "viewEncapsulation": "None"

    }

  },

  "defaultProject": "mi-dashboard"



샘플 컴포넌트를 생성한다.

  - --project옵션을 통해 어느 프로젝트안에 생성할지 선택한다.

  - / 로 path를 지정할 수 있다.

  - component 생성 명령 설명

$ ng g component layout/page --project=dashboard

CREATE apps/dashboard/src/app/layout/page/page.component.scss (0 bytes)

CREATE apps/dashboard/src/app/layout/page/page.component.html (23 bytes)

CREATE apps/dashboard/src/app/layout/page/page.component.spec.ts (614 bytes)

CREATE apps/dashboard/src/app/layout/page/page.component.ts (261 bytes)

UPDATE apps/dashboard/src/app/app.module.ts (555 bytes)


공통 라이브러리도 생성해 본다.

  - tag를 통해 소스 분석시 논리적 그룹을 주고, tag들 끼리의 의존관계를 설정할 수도 있다. 

  - library를 생성하면 <workspace>/angular.json, nx.json, tsconfig.json 파일에 자동으로 정보가 입력된다.

  - library 생성 명령 설명

$ ng g lib shared --tags=shared-lib

? In which directory should the library be generated?

? Which module should import the library?

? Would you like to add a routing configuration to the library? No

? Will this library be lazy loaded? No

? Would you like to generate an NgModule within the library? Yes

? Which Unit Test Runner would you like to use for the library? Jest (https://

jestjs.io/)

CREATE libs/shared/tsconfig.lib.json (705 bytes)

CREATE libs/shared/tslint.json (185 bytes)

CREATE libs/shared/src/index.ts (37 bytes)

... 생략


Unit Test는 Jest를 사용하고, e2e는 cypress를 사용하므로 Karma, Jasmine와 Protractor관련 내용은 삭제한다. 

  - package.json안에 karma, jamine관련 패키지 삭제 (jasmine-marbles 패키지는 제외)

  - karma.conf.json 파일삭제

  - yarn.lock, package-lock.json파일 삭제

  - node_modules를 제거하고 다시 npm install을 수행한다. 




NgRx/Platform 적용하기


Redux 패턴의 Angular 버전인 NgRx/platform을 적용한다. 엔터프라이즈 아키텍트를 적용하여 Store/State 접근방식을 SandBox를 통한 접근토록 만든다. libs/appState 에 공통적인 부분을 구현한다. Angular Enterprise Architecture Pattern을 참조한다.

  - Application Core Facade는 Parent Class로 Presentation Module에서 사용하는 Sandbox가 상속을 받는다.

  - "State Management" library를 생성한다. 여기에는 기본 설정항목과 None Visual Domain 영역에 대한 State관리를 관장한다. 

     이것은 forRoot가 된다.

  - Common UI는 Library별로 존재하며 State Management는 각 UI별로 구현한다. 

     이들은 forFeature가 된다.


Application을 위한 ngrx state를 생성한다. 

  - appState 명칭과 --module 옵션을 반드시 설정해야 한다. 

  - 해당 명령을 수행하면 ngrx/entity가 자동 설치되는데 v6.* 가 설치되므로 package.json에서 v7.*으로 변경하고 다시 npm install 수행한다. 

  - application레벨의 root state를 선택한다. (yes) => app.module.ts에 forRoot가 자동 설정된다.

  - facade도 yes를 선택한다.

  - 명령 옵션 목록

$ ng g ngrx appState --module=./apps/dashboard/src/app/app.module.ts

? Is this the root state of the application? Yes

? Would you like to add a Facade to your ngrx state Yes


생성 파일들


Redux에서는 action, reducer가 기본이고, (side) effect라는 부수효과는 reducer를 타기전 ajax 호출같은 async를 처리할 때 이용한다. selector는 state의 내용을 Domain 요구에 따라 조합해서 반환하는 서비스이다. 그럼 Facade는 무엇일까?

  - Redux패턴에서 state값을 조합해서 얻기위해 성능향상을 줄 수 있는 것이 reselector개념이고, 이를 selector에서 구현한다. 참조글

  - Redux패턴에서의 Facade 글을 참조한다. facade 서비스를 통해서 데이터를 가져온다. 데모 소스

  - Facade 서비스가 Presentation 컴포넌트에서 사용하는 Biz 로직을 담고 있는 SandBox이다. 

  


AppStateFacade는 forFeature에서 사용하는 common한 내용을 담는다. 즉 "Application core facade" 이다.

  - schematics을 커스텀으로 만들어 사용할 수 있다.

import { Injectable } from '@angular/core';


import { select, Store } from '@ngrx/store';


import { AppStatePartialState } from './app-state.reducer';

import { appStateQuery } from './app-state.selectors';

import { LoadAppState } from './app-state.actions';


@Injectable()

export class AppStateFacade {

  loaded$ = this.store.pipe(select(appStateQuery.getLoaded));

  allAppState$ = this.store.pipe(select(appStateQuery.getAllAppState));

  selectedAppState$ = this.store.pipe(

    select(appStateQuery.getSelectedAppState)

  );


  constructor(private store: Store<AppStatePartialState>) {}


  // 업무 메소드, Action을 생성하고 dispatch하는 문구가 존재한다.

  loadAll() {

    this.store.dispatch(new LoadAppState());

  }

}


forFeature에 대한 것은 libs 폴더 밑에 생성한다.

  - library 생성을 한다. 이때 옵션으로 --directory=<groupName>을 주면 라이브러리들을 directory명칭 밑으로 그룹핑할 수 있다. 

  - 생성된 library에 menu에 대한 feature 레벨 state를 생성한다. 

$ ng g lib menu --directory=state

? Which module should import the library?

? Would you like to add a routing configuration to the library? No

? Will this library be lazy loaded? No

? Would you like to generate an NgModule within the library? Yes

? Which tags would you like to add to the library? (used for linting)

? Which Unit Test Runner would you like to use for the library? Jest

CREATE libs/state/menu/tsconfig.lib.json (712 bytes)

CREATE libs/state/menu/tslint.json (188 bytes)

CREATE libs/state/menu/src/index.ts (41 bytes)  <== state 그룹 밑으로 menu library가 생성되었다. 

CREATE libs/state/menu/src/lib/state-menu.module.ts (164 bytes)

... 중략


다음으로 menu state를 생성한다. 

  - 반드시 library의 모듈을 수행하는 명령의 상대경로로 지정한다.

$ ng g ngrx menu --module=libs/state/menu/src/lib/state-menu.module.ts

? Is this the root state of the application? No

? Would you like to add a Facade to your ngrx state Yes

CREATE libs/state/menu/src/lib/+state/menu.actions.ts (731 bytes)

CREATE libs/state/menu/src/lib/+state/menu.effects.spec.ts (1147 bytes)

CREATE libs/state/menu/src/lib/+state/menu.effects.ts (842 bytes)

... 중략


state-menu.module.ts에 forFeature가 다음과 같이 자동 등록된다. forFeature는 lazy loading 또한 가능하다.

  - state에 대한 forFeature 등록

  - effect에 대한 forFeature 등록

import { NgModule } from '@angular/core';

import { CommonModule } from '@angular/common';

import { StoreModule } from '@ngrx/store';

import { EffectsModule } from '@ngrx/effects';

import {

  MENU_FEATURE_KEY,

  initialState as menuInitialState,

  menuReducer

} from './+state/menu.reducer';

import { MenuEffects } from './+state/menu.effects';

import { MenuFacade } from './+state/menu.facade';


@NgModule({

  imports: [

    CommonModule,

    StoreModule.forFeature(MENU_FEATURE_KEY, menuReducer, {

      initialState: menuInitialState

    }),

    EffectsModule.forFeature([MenuEffects])

  ],

  providers: [MenuFacade]

})

export class StateMenuModule {}


StateMenuModule을 app.module.ts에 등록한다. 

  - @jm/state/menu 경로로 import한다. 이는 <workspace>/tsconfig.json에 path가 자동 설정되기에 가능하다. 

import { StateMenuModule } from '@jm/state/menu';


@NgModule({

  declarations: [AppComponent, PageComponent],

  imports: [

    BrowserModule,

    NxModule.forRoot(),

    RouterModule.forRoot([], { initialNavigation: 'enabled' }),

    StoreModule.forRoot(

      { appState: appStateReducer },

      {

        initialState: { appState: appStateInitialState },

        metaReducers: !environment.production ? [storeFreeze] : []

      }

    ),

    EffectsModule.forRoot([AppStateEffects]),

    !environment.production ? StoreDevtoolsModule.instrument() : [],

    StoreRouterConnectingModule,


    StateMenuModule

  ],

  providers: [AppStateFacade],

  bootstrap: [AppComponent]

})

export class AppModule {}


effect 클래스를 보면 DataPersistence 헬퍼 클래스를 Nx에서 제공한다. 

  - async 처리에 대한 추상화이다. 

  - 4가지 주요 헬퍼 메소드 제공

    + optimisticUpdate: 요청값을 client에 먼저 반영하고 만일 backend 오류 발생시 이전 상태로 복원

    + pessimisticUpdate: 요청값을 backend에 반영하고 이후 client에 반영

    + fetch: 같은 Action에 대한 다중 요청은 가장 최신 것만 반영함. pessimisticUpdate이면서 같은 Action에 따른 요청은 최신만 반영하는 것.

    + navigation: routing될 때 effect 자동 호출

  - DataPersistence에 대한 상세 설명

  - Angular Application State관리 방법

import { Injectable } from '@angular/core';

import { Effect, Actions } from '@ngrx/effects';

import { DataPersistence } from '@nrwl/nx';


import { MenuPartialState } from './menu.reducer';

import {

  LoadMenu,

  MenuLoaded,

  MenuLoadError,

  MenuActionTypes

} from './menu.actions';



@Injectable()

export class MenuEffects {

  @Effect() loadMenu$ = this.dataPersistence.fetch(

    MenuActionTypes.LoadMenu, 

    {

      run: (action: LoadMenu, state: MenuPartialState) => {

        // Your custom REST 'load' logic goes here. For now just return an empty list...

        return new MenuLoaded([]);

      },


      onError: (action: LoadMenu, error) => {

        console.error('Error', error);

        return new MenuLoadError(error);

      }

  });


  constructor(

    private actions$: Actions,

    private dataPersistence: DataPersistence<MenuPartialState>

  ) {}

}



<참조>

- Nx Workspace 홈페이지

- Nx Github

- Angular Workspace의 Schematics 설정 목록

Nx workspace에서 component 생성하기 명령

- Angular Enterprise Architecture Pattern

- NgRx Schematics 설정

- Redux의 reselector를 통한 성능향상

- NgRx Facade 이해

- Angular Application State관리 방법

- Ionic + Angular + ngrx 사례

posted by 윤영식
2018. 12. 27. 15:27 Angular/Architecture

Angular CLI v6.* 이후 Multi Application을 위한 Workspace개념이 도입되었다. 공통 Module을 통해 하나의 폴더안에서 여러 애플리케이션을 만들 수 있는 방법에 대해 알아본다. 




Schematics


스케메틱스는 workflow 툴이다. 

  - 프로젝트에 파일을 생성하고

  - 기존 코드를 변경하고

  - 환경 옵션을 추가하거나 프레임워크를 추가할 수 있다. 


스케메틱스는 Angular CLI의 코드 스케폴딩에 사용하며 다음 목표를 지향하여 개발되었다. 

  - 사용 및 개발이 쉬워야 한다

  - 확장 및 재상용성이 좋아야 한다

  - CLI동작시 부작용을 제거할 수 있어야 한다.

  - 비동기성을 지원한다.


Tree

  - 이미 존재하는 파일 관계를 작는 데이터 구조체이다. 

  - 파일을 수정하거나 생성하고 찾아 갈때 사용한다.

  - 스케메틱의 Start point가 된다. 

  - 하나의 스케메틱 Tree를 다른 스케메틱 Tree로 전달할 수 있다. 

  - create, delete, rename, overwrite 내가지 함수를 제공한다.


나만의 스케메틱스 만들기 

  - Node v6.9 이상 설치

  - schematics 실행환경을 만들기 위해 shcematics-cli를 설치한다. 

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

// 빈 스케메틱스 프로젝트 생성

$ schematics blank --name=my-project

$ cd my-project


Collections

  - 이름을 갖는 schematics의 집합이다. 이것은 사용자에 의해 발행되고 설치될 수 있다. 

  - 예로 @schematics/angular collection이 있다. 이것은 component, module, application 등에 대한 schematics를 가지고 있다. 

  - 생성한 my-project는 하나의 schematics만을 가지고 있고, my-project/src/collection.json 에 정의되어 있다. 

  - schematics key안에 하나의 my-project schematic 이 설정되어 있다.

  - factory key는 자바스크립트 펑션 위치를 설정한다. 이것은 RuleFactory라 한다. 

// src/collection.json

{

  "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",

  "schematics": {

    "my-project": {

      "description": "A blank schematic.",

      "factory": "./my-project/index#myProject"

    }

  }

}


// src/my-project/index.ts

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


export function myProject(_options: any): Rule {

  return (tree: Tree, _context: SchematicContext) => {

    return tree;

  };

}


Rule

  - Tree를 받아 Tree를 반환하는 함수이다. 

  - Rule이 스케메틱스의 핵심이다. 

  - Factory 함수는 입력 options 아규먼트를 받아 원하는 것을 처리 후 다시 Rule을 반환한다. 

  - 옵션은 CLI의 경우 command line 아규먼트로 전달되는 값이다. (보통 --name=<value> 같이 전달함)

 

사용자가 만든 스케메틱스를 수행하기 

  - dry-run은 스케메틱스 자신안에서 수행할 수 있게 한다. default는 false 이다.

  - 우리가 만든 스케메틱스는 애플리케이션안에서 사용하는 것이다. 따라서 자기 자신안에서 스케메틱스 검증을 해보려면 dry-run 옵션을 준다.

  - 만들어진 스케메틱스를 디버깅 할 수 있다. 

$ npm run build


// dry-run 수행시, 가급적 사용하지 말자, 별도의 temporary 폴더에서 dry-run없이 테스트 한다. 

$ schematics .:my-project --name=test --dry-run=true


// 디버깅

$ node --inspect-brk $(which schematics) .:my-project --name=test


다른 스케메틱스를 함께 사용하기 

  - chain을 통해 기존 @schamatics/angular의 component 생성하는 것을 이용한다. 

  - Angular component를 만든 다음 상단에 license 문구를 추가한다. 

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


const licenseText = `

/**

 * @license

 * Copyright Google Inc. All Rights Reserved.

 *

 * Use of this source code is governed by an MIT-style license that can be

 * found in the LICENSE file at https://angular.io/license

 */

`;


export function myProject(options: any): Rule {

  return chain([

    externalSchematic('@schematics/angular', 'component', options),

    (tree: Tree, _context: SchematicContext) => {

      tree.getDir(options.sourceDir)

          .visit(filePath => {

            if (!filePath.endsWith('.ts')) {

              return;

            }

            const content = tree.read(filePath);

            if (!content) {

              return;

            }


            // Prevent from writing license to files that already have one.

            if (content.indexOf(licenseText) == -1) {

              tree.overwrite(filePath, licenseText + content);

            }

          });

      return tree;

    },

  ]);

}


수행해 보자.

// my-project schematics 폴더안에서 의존관계있는 @schematics/angular 설치

$ npm install --save @schematics/angular

$ npm run build


// 신규 프로젝트 생성하고, my-project schematics 를 npm link 건다.

$ cd ../

$ ng new <otherProjectName>

$ cd <otherProjectName>

$ npm link <my-project schematics path>


// schematics:schematic 을 호출한다. angular module의 declarations에도 자동 추가된다. 

$ ng g my-project:my-project

? What name would you like to use for the component? hi

CREATE src/app/hi/hi.component.css (0 bytes)

CREATE src/app/hi/hi.component.html (21 bytes)

CREATE src/app/hi/hi.component.spec.ts (600 bytes)

CREATE src/app/hi/hi.component.ts (253 bytes)

UPDATE src/app/app.module.ts (537 bytes)




Multi Application을 위한 Nx Workspace


Nx Workspace는 nrwl에서 만든 multi application 개발을 위한 Angular CLI에 대한 확장팩이다. 다음 3가지의 향상시키기 위해 만들어졌다. 

  - 생산성: 초시 셋업시간을 절약한다.

  - 일관성: 기업용 애플리케이션을 위한 좀 더 향상된 코드 제너레이터를 제공하고, 일관된 물리적 공간과 컨벤션을 제공한다.

  - 안정성: 분석기능 강화




Workspace에서 작업하기

  - 단일 레파지토리에서 Multi Application과 Library에 대한 개발을 수행한다.

    + Unified versioning: 하나의 레파지토리 사용에 따른 

    + Promotes code sharing and reuse: lib모듈을 통한 공유

    + Easier dependency management: 하나의 node_modules만 사용, 하나의 build setup

    + Refactoring benefits: code editors 지원, 변경이 전체 애플리케이션에 반영

    + Consistent developers experience: 공유 코드 변경에 대한 전체 애플리케이션 유효성 체크 가능



Nx Workspace 만들기

create-nx-workspace 명령어를 통해 nx 기반 angular workspace를 생성한다. 마치 create-react-app과 같은 역할이다. 

  - npmScope: 그림처럼 NPM Scope로 library를 접근하는 @my-company와 같은 npm scope를 설정


예로 @angular가 npm scope이다. 


  - directory workspace의 폴더명 변경

$ npm i -g @nrwl/schematics  @angular/cli


// command: create-nx-workspace <workspace name> --directory=<workspace별칭폴더명> --npm-scope=<library접근 scope>

$ create-nx-workspace my-project-suite --npm-scope=apple




Multi Application & Library 생성하기


Nx Workspace에 application과 library를 생성한다. Angular CLI Workspace에서 만들어 지는 폴더 구조와 다음과 같은 차이가 있다. 

  - apps: apps폴더 밑으로 Application별 폴더가 존재한다. 

  - libs: application에서 공유하는 Angular Module별 폴더가 존재한다.


애플리케이션 프로젝트에 대한 정보는 angular.json에서 확인할 수 있다. 

{

  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",

  "version": 1,

  "newProjectRoot": "",

  "projects": {}, <-- 프로젝트 즉, 애플리케이션은 아직 등록되지 않았다. 

  "cli": {

    "warnings": {

      "typescriptMismatch": false,

      "versionMismatch": false

    },

    "defaultCollection": "@nrwl/schematics", <-- nrwl/schematics를 사용한다. 

    "packageManager": "npm"

  }

}


nx.json은 Nx Workspace특화된 환경값을 갖는다. 

{

  "npmScope": "apple",

  "implicitDependencies": {

    "angular.json": "*",

    "package.json": "*",

    "tsconfig.json": "*",

    "tslint.json": "*",

    "nx.json": "*"

  },

  "projects": {}

}


그외 tsconfig.json에 paths와 tslin.json의 nx-enforce-module-boundaries 설정, 그리고 package.json에 Nx를 위한 별도 script들이 존재한다. 


apps폴더 밑으로 프로젝트 추가하기

  - 명령: ng g app <application name>

  - ng g app --help 로 생성 옵션을 볼 수 있다. 예로 --routing 옵션을 주면 routing module이 자동 설정된다. 또는 생성시 yes 를 선택해되 된다. 

$ ng g app app-one


// 다음을 선택했다. 

? In which directory should the application be generated?

? Would you like to add Angular routing? Yes

? Which stylesheet format would you like to use? SCSS   [ http://sass-lang.com]

? Which Unit Test Runner would you like to use for the application? Jest   [ https://jestjs.io ]

? Which E2E Test Runner would you like to use for the application? Cypress[ https://www.cypress.io ]

? Which tags would you like to add to the application? (used for linting)


애플리케이션 app-one을 위해 다음과 같은 두개 폴더가 생성된다. 


만들어진 애플리케이션을 실행해 보자. 

  - ng serve <application name>

  - default port는 4200이다. 여러개의 애플리케이션을 동시 실행하고 싶다면 --port 옵션으로 포트를 서로 틀리게 설정한다. 또는 angular.json에 설정할 수 있다. 

$ ng serve app-one


libs폴더 밑으로 공유 라이브러리 추가하기

  - 라이브러리는 Angular Module이다.

  - ng g lib <library name> 

$ ng g lib adk

? In which directory should the library be generated?

? Which module should import the library?

? Would you like to add a routing configuration to the library? No

? Will this library be lazy loaded? No

? Would you like to generate an NgModule within the library? Yes

? Which tags would you like to add to the library? (used for linting)

? Which Unit Test Runner would you like to use for the library? Jest (https://jestjs.io/)


생성을 하게되면 libs/adk 폴더가 생성되고, angular.json에 projectType으로 library가 자동 등록된다. (nx.json에도 자동 등록됨)


lazy loading되는 library module 생성

  - --routing이 설정된 모듈

  - lazy loading되는 상위 모듈: 어차피 애플리케이션도 라이브러리도 모듈이다.

  - --lazy 옵션을 직접주거나 아래처럼 선택할 수 있다. 

$ ng g lib login --routing --parent-module=./apps/app-one/src/app/app.module.ts


? In which directory should the library be generated?

? Will this library be lazy loaded? Yes

? Would you like to generate an NgModule within the library? Yes

? Which tags would you like to add to the library? (used for linting)

? Which Unit Test Runner would you like to use for the library? Jest (https://jestjs.io/)


routing 설정을 하게되면 login.module.ts와 app-one의 app.module.ts 안의 설정은 다음과 같다. 

  - @apple 이라는 npm scope가 자동으로 붙는다. 

// libs/login/src/lib/login.module.ts

@NgModule({

  imports: [

    CommonModule,


    RouterModule.forChild([

      /* {path: '', pathMatch: 'full', component: InsertYourComponentHere} */

    ])

  ]

})

export class LoginModule {}


// apps/app-one/src/app/app.module.ts

@NgModule({

  declarations: [AppComponent],

  imports: [

    BrowserModule,

    NxModule.forRoot(),

    RouterModule.forRoot(

      [{ path: 'login', loadChildren: '@apple/login#LoginModule' }],

      { initialNavigation: 'enabled' }

    )

  ],

  providers: [],

  bootstrap: [AppComponent]

})

export class AppModule {}


루트의 tsconfig.json에는 library module에 대한 paths 정보가 자동 설정된다. 

    "lib": [

      "es2017",

      "dom"

    ],

    "baseUrl": ".",

    "paths": {

      "@apple/adk": [

        "libs/adk/src/index.ts"

      ],

      "@apple/login": [

        "libs/login/src/index.ts"

      ]

    }




Multi Application 빌드하기 


angular.json의 architect에는 build와 serve에 대한 환경설정이 있다.

      "architect": {

        "build": {

          "builder": "@angular-devkit/build-angular:browser",

          "options": {

            "outputPath": "dist/apps/app-one",

            "index": "apps/app-one/src/index.html",

            "main": "apps/app-one/src/main.ts",

            "polyfills": "apps/app-one/src/polyfills.ts",

            "tsConfig": "apps/app-one/tsconfig.app.json",

            "assets": [

              "apps/app-one/src/favicon.ico",

              "apps/app-one/src/assets"

            ],

            "styles": [

              "apps/app-one/src/styles.scss"

            ],

            "scripts": []

          },

          "configurations": {

            "production": {

              ....

             }

           }


빌드 명령

애플리케이션을 빌드한다

  - ng build <application name> --prod

  - nx workspace command 목록

$ ng build app-one --prod


라이브러리를 빌드하려면 라이브러리 생성할 때 --publishable 옵션을 주어서 생성한다. 그러면 angular.json파일의 "architect"에 "build"옵션이 추가된다. library build할 때는 ng-packagr를 이용하여 어디에서든 사용할 수 있는 APF v6가 적용된다. APF는 Angular Package Format의 약어이다. 

 $ ng g lib ui --publishable --routing --parent-module=./apps/app-one/src/app/app.module.ts


// angular.json 

    "ui": {

      "root": "libs/ui",

      "sourceRoot": "libs/ui/src",

      "projectType": "library",

      "prefix": "apple",

      "architect": {

        "build": {

          "builder": "@angular-devkit/build-ng-packagr:build",

          "options": {

            "tsConfig": "libs/ui/tsconfig.lib.json",

            "project": "libs/ui/ng-package.json"

          }

        },


Angular Pakage Format v6 지원 목록


ui라는 라이브러리 빌드하기 

$ ng build ui

Building Angular Package

Building entry point '@apple/ui'

Compiling TypeScript sources through ngc

Bundling to FESM2015

Bundling to FESM5

Bundling to UMD

Minifying UMD bundle

Copying declaration files

Writing package metadata

Removing scripts section in package.json as it's considered a potential security vulnerability.

Built @apple/ui

Built Angular Package!

 - from: /Users/dowonyun/mobicon/projects/bistel/prototyping/my-project-suite/libs/ui

 - to:   /Users/dowonyun/mobicon/projects/bistel/prototyping/my-project-suite/dist/libs/ui


// 다양한 번들 파일이 생성됨 



$schema와 schema.json 개념

Angular Workspace에 대한 schema를 강제하기 위하여 schema.json 파일을 angular.json의 $schema에 설정한다. 

  - Angular Workspace Schame에 대한 Json 스펙

  - Angular CLI의 Schematics 에 목록: 각 폴더 밑에 schema.json 파일이 존재한다. 

  - schematics 키의 값은 workflow를 수행할 때 적용할 옵션을 설정할 수 있다. 

     지정가능한 옵션 목록

"schematics": {

        "@schematics/angular:component": {

          "styleext": "scss",

          "changeDetection": "OnPush",

          "viewEncapsulation": "None",

          "export": true

        }

},




<참조>

- Schematics 소개

- 2018 FEConf, 고재도님의 Schematics 소개영상

- Angular CLI의 Workspace 과 Schematics 개념

- Angular CLI command 목록

- Nrwl Nx Workspace  홈페이지

- Nx Github 

- Nx Workspace 온라인 강좌 (Free)

- Angular Package Format(APF) 개념 강좌

- APF를 만들어주는 ng-packagr 소스 및 설명

- APF v6 스펙

- ng-packagr 소개

posted by 윤영식
prev 1 next