블로그 이미지
Peter Note
Web & LLM FullStacker, Application Architecter, KnowHow Dispenser and Bike Rider

Publication

Category

Recent Post

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 Peter Note
2017. 11. 15. 16:31 Meteor/Angular + Meteor

Angular CLI와 Meteor를 분리하고, Meteor를 단순히 API 서버로 사용하면서 Angular CLI는 Webpack Dev Server를 통해 4200 port로 브라우져에서 접속하면 Meteor Client는  3000 port를 통해 Meteor Server와 DDP 통신을 한다. (이전 블로그 참조) 이번에는 외부 라이브러리로 Clarity CSS Framework을 추가해 본다. 





Clarity CSS Framework


Twitter Bootstrap 처럼 CSS Framework이지만, clarity-ui, clarity-icon, clarity-angular 3개의 파트로 구분된다. clarity-ui는 css만 존재하고, clarity-icon은 이름처럼 아이콘에 관련된 부분이며, clarity-angular는 Angular 컴포넌트를 제공한다. 


  - Clarity 홈페이지

  - Clarity 소스

  - Clarity Seed 소스


// 아이콘 관련

$ npm install clarity-icons --save

$ npm install @webcomponents/custom-elements@1.0.0 --save


// UI CSS

$ npm install clarity-ui --save


// Angular 컴포넌트 

$ npm install clarity-angular --save


Clarity-Angular는 ngModule에서 import를 하면되고 나머지는 아래 장의 설명처럼 ng eject 이전 상태라면 angular-cli.json 에 설정하고, ng eject가 되었다면 webpack.config.js에 설정한다. 

// 메인 모듈

import { ClarityModule } from 'clarity-angular';


@NgModule({

imports: [

BrowserModule,

ClarityModule.forRoot()

],

...

})

export class AppModule {} 





@angular/cli 설정을 webpack.config.js로 옮기기


Clarity Seed를 보면 @angular/cli 기반으로 생성되어 있고, angluar-cli.json 안에 설정이 다음과 같이 되어있다. 진행중인 프로젝트에 Clarity icons, ui에 대한 외부 경로 설정을 한다. 

"styles": [
"styles.css",
"../node_modules/clarity-icons/clarity-icons.min.css",
"../node_modules/clarity-ui/clarity-ui.min.css"
],
"scripts": [
"../node_modules/@webcomponents/custom-elements/custom-elements.min.js",
"../node_modules/clarity-icons/clarity-icons.min.js"
],


해당 설정을 이전강좌의 Angular CLI + Meteor 프로젝트의 angular-cli.json을 넣고 ng eject를 하게 되면 다음과 같은 내용이 webpack.config.js에 자동 설정된다. 

  - Module안에 "exclude"와 "include"의 "src/styles.css"이 있는 모든 곳에 설정.

  - Plugin안에 new ConcatPlugin내용 추가

"module": {

{

"exclude": [

path.join(process.cwd(), "src/styles.css"),

path.join(process.cwd(), "node_modules/clarity-icons/clarity-icons.min.css"),

path.join(process.cwd(), "node_modules/clarity-ui/clarity-ui.min.css")

]

...

},

{

"include": [

path.join(process.cwd(), "src/styles.css"),

path.join(process.cwd(), "node_modules/clarity-icons/clarity-icons.min.css"),

path.join(process.cwd(), "node_modules/clarity-ui/clarity-ui.min.css")

]

...

}

...

},

"plugins": [

new ConcatPlugin({

"uglify": false,

"sourceMap": true,

"name": "scripts",

"fileName": "[name].bundle.js",

"fileToConcat": [

"node_modules/@webcomponents/custsom-elements/custom-elements.min.js",

"node_modules/clarity-icons/clarity-icons.min.js"

]

})

]





Clarity 테스트


Clarity CSS Framework은 업무적으로 요하는 컴포넌트 요소를 잘 정리해 놓았다. Application Layout에 대한 내역을 app.component.html에 추가한다. 

<div class="main-container">
<div class="alert alert-app-level">
Alert
</div>
<header class="header header-6">
Angular Meteor
</header>
<nav class="subnav">
Navigation
</nav>
<div class="content-container">
<div class="content-area">
Main
</div>
<nav class="sidenav">
Side Menu
</nav>
</div>
</div>


결과 화면





Clarity Icon 선택적으로 적용하기


plugins부분에 clarity-icons/clarity-icons.min.js 은 전체 아이콘을 포함하고 있다. 전체을 적용하지 않고, Core와 일부분만 적용하고 싶을 경우 다음과 같이 한다. 


// webpack.config.js에서 clarity-icons.min.js 제거

"plugins": [

new ConcatPlugin({

"uglify": false,

"sourceMap": true,

"name": "scripts",

"fileName": "[name].bundle.js",

"fileToConcat": [

"node_modules/@webcomponents/custsom-elements/custom-elements.min.js"

]

})

]


src/main.ts안에 import

import 'clarity-icons';
import 'clarity-icons/shapes/essential-shapes';
import 'clarity-icons/shapes/technology-shapes';


app.component.html안에 clr-icon 적용 테스트. 자세한 사항은 문서를 참조한다. Clarity-icons은  svg icon으로 사용자 정의 아이콘을 추가 할 수도 있다.

<div class="content-area">
<p><clr-icon shape="user" size="24"></clr-icon> lives in the Core Shapes set.</p>
<p><clr-icon shape="pencil" size="24"></clr-icon> lives in the Essential Shapes set.</p>
<p><clr-icon shape="tablet" size="24"></clr-icon> lives in the Technology Shapes set.</p>
</div>


posted by Peter Note
2017. 11. 8. 17:20 Meteor/Angular + Meteor

Ionic CLI 와 Meteor CLI 로 프로젝트 구성하기는 모바일 프로젝트를 진행할 때 사용하면 되고, 이번에는 Angular CLI 와 Meteor CLI를 통해 프로젝트 구성을 어떻게 하는지 살펴본다. 




Webpack 기반 프로젝트 초기화


Angular CLI를 통해 프로젝트를 생성한다. @angular/cli v1.5.0이 설치되고, webpack은 v3.8.1 이고, 내부적으로 @angular-devkit, @ngtools/webpack, @schematics등이 사용된다.

$ npm install -g @angular/cli


@angular/CLI 설치후 프로젝트를 생성한다. ng <command>의 상세 내용은 위키를 참조한다.

$ ng new <projectName>


Webpack 환경파일을 수정해야 하므로, eject 명령을 수행하고, 결과로 출력된 가이드에 따라 "npm install" 명령을 수행한다. eject 명령에 대한 다양한 options은 위키를 참조한다. eject시에 옵션을 주면 옵션이 적용된 webpack.config.js가 생성된다.

$ ng eject --aot --watch


====================================================

Ejection was successful.


To run your builds, you now need to do the following commands:

   - "npm run build" to build.

   - "npm test" to run unit tests.

   - "npm start" to serve the app using webpack-dev-server.

   - "npm run e2e" to run protractor.


Running the equivalent CLI commands will result in an error.

====================================================

Some packages were added. Please run "npm install".


$ npm install

$ npm run build


eject를 수행한 경우에는 "ng serve" 명령으로 테스트 서버를 뛰울 수 없다. package.json에 적용된 스크립트인 "npm start"를 수행하고 4200 port로 브라우져에서 

$ npm start


 10% building modules 3/3 modules 0 activeProject is running at http://localhost:4200/

webpack output is served from /

....


Webpack 환경 내역은 크게 entry, output, module (for loader), plugins 로 구성된다. (참조)

  - entry: 파일 위치

  - output: 결과 위치

  - module: css, .ts, .html 파일 관리 및 변환기 -> 자바스크립트 모듈로 만들기 위한 것. postfix가 "-loader" 이다. 로더는 파일단위 처리

  - plugins: 압축, 핫로딩, 복사, 옮기기등. 플러그인은 번들된 결과물을 처리





Angular CLI 환경에 Meteor 설정



이전 포스트처럼 루트에 api 폴더를 만들고 이를 Meteor의 백앤드로 사용토록 설정한다.

// webpack.config.js


const webpack = require('webpack');

...

resolve: {

  alias: {

    'api': path.resovle(__dirname, 'api/server'),

    ...

  }

}


externals: [ resolveExternals ],


plugins: [ ..., new webpack.ProvidePlugin({ __extends: 'typescript-extends' }) ],


node: { ..., __dirname: true }


// 맨 마지막에 넣음 

function resolveExternals(context, request, callback) {

  return resolveMeteor(request, callback) ||

    callback();

}

 

function resolveMeteor(request, callback) {

  var match = request.match(/^meteor\/(.+)$/);

  var pack = match && match[1];

 

  if (pack) {

    callback(null, 'Package["' + pack + '"]');

    return true;

  }

}


루트에 있는 tsconfig.json에 Meteor 백앤드 관련 내용을 추가한다.

"compilerOptions: {

"baseUrl": ".",

"module": "commonjs",

...

"skipLibCheck": true,

"stripInternal": true,

"noImplicitAny": false,

"types": [ "@types/meteor" ]

},

"include": [ ..., "api/**/*.ts" ],

"exclude": [ ..., "api/node_modules", "api" ]


src/tsconfig.app.json과 tsconfig.spec.json안에 api에 대한 exclude도 설정해야 한다.

// src/tsconfig.app.json

"exclude": [

   ...,

   "../api/node_modules"

]


// src/tsconfig.spec.json

"exclude": [ "../api/node_modules" ]


관련 패키지를 설치한다.

$ npm install --save-dev typescript-extends

$ npm install --save-dev @types/meteor

$ npm install --save-dev tmp




Meteor Server API 생성 및 설정


Meteor CLI를 설치하고 api 명으로 Meteor 프로젝트를 생성한다.

$ curl https://install.meteor.com/ | sh

$ meteor create api


api 폴더 밑의 필요없는 폴더를 삭제하고 루트에 있는 것으로 대체한다.

$ cd api

// 삭제

api$ rm -rf node_modules client package.json package-lock.json


// 심볼릭 링크

api$ ln -s ../package.json

api$ ln -s ../package-lock.json

api$ ln -s ../node_modules

api$ ln -s ../src/declarations.d.ts


Meteor 백앤드를 Typescript 기반으로 개발하기 위한 패키지를 설치한다.

api$ meteor add barbatus:typescript


api$ cd ..

$ npm install --save babel-runtime

$ npm install --save meteor-node-stubs

$ npm install --save meteor-rxjs


Typescript의 tsconfig.json 파일을 api 폴더안에 생성하고 다음 내역을 붙여넣는다.

{

  "compilerOptions": {

    "allowSyntheticDefaultImports": true,

    "declaration": false,

    "emitDecoratorMetadata": true,

    "experimentalDecorators": true,

    "lib": [

      "dom",

      "es2017"

    ],

    "module": "commonjs",

    "moduleResolution": "node",

    "sourceMap": true,

    "target": "es6",

    "skipLibCheck": true,

    "stripInternal": true,

    "noImplicitAny": false,

    "types": [

      "@types/meteor"

    ]

  },

  "exclude": [

    "node_modules"

  ],

  "compileOnSave": false,

  "atom": {

    "rewriteTsconfig": false

  }

}


Meteor의 server/main.js를 main.ts로 바꾼다. 위에서 설치한 meteor-rxjs는 클라이언트단의 Meteor를 RxJS Observable기반으로 사용할 수 있도록 한다.

// 예) Meteor 클라이언트단 Collection 구성

import { MongoObservable } from 'meteor-rxjs';


export const Chats = new MongoObservable.Collection('chats');




Meteor Client 준비


Meteor Server <-> Client 연동을 위해 Client를 Bundling한다.

$ sudo npm install -g meteor-client-bundler


번들링시에 Meteor Server 기본 주소는 localhost:3000 으로 설정된다. Meteor Client는 DDP를 이용하기 때문에 번들할 때 --config 옵션 또는 --url 옵션으로 Meteor Server 위치를 지정한다.  -s 옵션을 주면 Client<->Server 같은 버전의 패키지를 사용하고 -s 옵션을 주지않으면 config 설정내용을 참조한다. (참조)

$ meteor-client bundle --destination meteor.bundle.js --config bundler.config.json


// config file

{ "release": "1.6", "runtime": { "DDP_DEFAULT_CONNECTION_URL": "http://1.0.0.127:8100" }, "import": [ "accounts-base", "mys:accounts-phone", "jalik:ufs@0.7.1_1", "jalik:ufs-gridfs@0.1.4" ] }


package.json에 번들링 명령을 등록하고 수행한다. 

"scripts": {

   ...,

   "meteor-client:bundle": "meteor-client bundle -s api"

}


//번들링 - 최초 한번만 수행한다.

$ npm run meteor-client:bundle


Angular 클라이언트에서 Meteor Client를 사용하기 위해 src/main.ts에서 "meteor-client"를 import한다.

import "meteor-client";




Collection 생성하고 Meteor 기능 사용 테스트


api/server 에 model을 하나 만든다. Angular와 Meteor가 같이 사용하는 모델 타입이다.

// api/server/models.ts

export enum MessageType {

  TEXT = <any>'text'

}


export interface Chat {

  _id?: string;

  title?: string;

  picture?: string;

  lastMessage?: Message;

  memberIds?: string[];

}


export interface Message {

  _id?: string;

  chatId?: string;

  senderId?: string;

  content?: string;

  createdAt?: Date;

  type?: MessageType;

  ownership?: string;

}


api/server/collections 폴더를 생성하고 Chat 컬렉션을 생성한다. meteor-rxjs 는 RxJS로 Mongo Client를 wrapping해 놓은 것으로 Rx방식으로 Mongo Client를 사용할 수 있게 한다.

// api/server/collections/chats.ts

import { MongoObservable } from 'meteor-rxjs';

import { Chat } from '../models';


export const Chats = new MongoObservable.Collection<Chat>('chats'); 


// api/server/collections/messages.ts

import { MongoObservable } from 'meteor-rxjs';

import { Message } from '../models';


export const Messages = new MongoObservable.Collection<Message>('messages');


api/server/main.ts안에 샘플 데이터를 넣는다.

$ npm install --save moment


// api/server/main.ts

import { Meteor } from 'meteor/meteor';

import { Chats } from './collections/chats';

import { Messages } from './collections/messages';

import * as moment from 'moment';

import { MessageType } from './models';


Meteor.startup(() => {

  // code to run on server at startup

  if (Chats.find({}).cursor.count() === 0) {

    let chatId;


    chatId = Chats.collection.insert({

      title: 'Ethan Gonzalez',

      picture: 'https://randomuser.me/api/portraits/thumb/men/1.jpg'

    });


    Messages.collection.insert({

      chatId: chatId,

      content: 'You on your way?',

      createdAt: moment().subtract(1, 'hours').toDate(),

      type: MessageType.TEXT

    });


    chatId = Chats.collection.insert({

      title: 'Bryan Wallace',

      picture: 'https://randomuser.me/api/portraits/thumb/lego/1.jpg'

    });


    Messages.collection.insert({

      chatId: chatId,

      content: 'Hey, it\'s me',

      createdAt: moment().subtract(2, 'hours').toDate(),

      type: MessageType.TEXT

    });

  }

});


다음으로 Angular에 Chat 컬렉션을 사용한다.

// src/app/app.component.ts

import { Component, OnInit } from '@angular/core';

import { Chats } from '../../api/server/collections/chats';

import { Chat } from '../../api/server/models';


@Component({

  selector: 'app-root',

  templateUrl: './app.component.html',

  styleUrls: ['./app.component.css']

})

export class AppComponent implements OnInit {

  title = 'app';

  chats: Chat[];

  ngOnInit() {

    Chats.find({}).subscribe((chats: Chat[]) => this.chats = chats );

  }

}


// src/app/app.component.html 에 추가

<div> {{ chats | json }} </div>




Angular & Meteor 기동


Meteor 기동

$ cd api

api$ meteor


Angular 기동

$ npm start


Webpack dev server는 4200이고meteor client는 server에 websocket 3000 port로 접속을 한다. Meteor 의 mongo로 접속해서 chats collection을 확인해 본다.

$ meteor mongo

MongoDB shell version: 3.2.15

connecting to: 127.0.0.1:3001/meteor

Welcome to the MongoDB shell.

For interactive help, type "help".

For more comprehensive documentation, see

http://docs.mongodb.org/

Questions? Try the support group

http://groups.google.com/group/mongodb-user

meteor:PRIMARY> show collections

chats

messages



하단에 Chat 내역이 json 형식으로 출력된다.




<참조>


- Webpack v3 환경설정 요약

- Meteor Client bundler의 작도방식 by Uri

- Meteor Client Bundler Github


posted by Peter Note
2016. 4. 18. 20:46 Electron & Ionic

Angular2-seed에 Desktop 애플리케이션을 만들수 있는 Electron 기술과 네이티브 모바일 앱을 만들 수있는 NativeScript을 붙여서 확장한 Seed가 Angular2-seed-advanced 이다. Advanced 시드의 내용을 보면 Typescript의 장점을 살려서 OOP 방식으로 Build 환경과 코드를 재사용하면서 Web, Desktop, Native Mobile App을 만들 수 있는 환경을 제공한다. Advanced를 참조해서 Angular2-seed를 기반으로 Hybrid Mobile App을 만들 수 있는 Ionic2 프레임워크를 합쳐서  Web, Hybrid Mobile App용 Seed를 만들고자 한다. 기존에 나와 있는 ionic2-seed도 참조해 App 개발을 위한 SDK도 포함하는 Advanced 버전을 만든다. 





1. Action Plan


어떤 작업을 해야할지 마인드 맵으로 그려보았다. 먼저 Angular2의 Seed 소스를 분석하고 Ionic2의 새로운 개념을 알아본다. 그리고 Angular2 Code Style 과 Sass 스타일을 정할 예정이다. 분석이 끝나면 Gulp 기반으로 Web과 Mobile을 위한 빌드 환경을 만든다. 그리고 Web, Mobile 개발 환경의 폴더 구조를 만든다. Ionic2는 별도의 Ionic CLI(Command Line Interface)를 제공하기 때문에 기존 Angular2-seed와 어떻게 합칠지가 관건이다. 다음으로 Framework을 Hierarchical Layer로  SDK, Biz Context, Common 로 구성할 것이다. Angular2는 ES2015와 TypeScript 둘다 지원하고 ES2015의 Module System 문법을 사용할 수 있다. 즉, 컴포넌트를 모듈단위로 나누고 역할에 따라 계층을 나누어 Framework을 구성한다. 


환경과 프레임워크가 준비되면 샘플 프로토타입핑을 통해 Angular2-seed-ionic2가 잘 도는지 확인을 하고 일반적인 화면 예제를(MVP) 만들어 다양한 예를 통해 가이드 한다.  


필요 가이드 문서는 다음과 같다. 


  - Code Style Guide

  - Environment Guide

  - Framework Guide 

  - 10-Minutes Starting Guide (with prototyping)

  - Several Sample Guide (with MVP)






2. Project seed contents


환경과 프레임워크에 대한 자세한 내용이다. 환경은 Web과 Hybrid Mobile App을 위한 빌드와 테스트 환경을 갖추는게 목표이다. 그리고 프레임워크에는 계층형 레이어를 통해 필요한 요소를 Angular2 Components로 만들어 놓을 것이다. 일단 다음과 같은 과정을 거치면 좋을 것 같다. 


  - Step 1 : Angular2-seed-ionic2를 통해 Environment와 Framework을 최초에 만든다. 

  - Step 2 : Anguar-CLI를 통해 Angular2 Component 코드를 자동생성한다. (옵션)



대략 한달간의 기간으로 바로 Prototyping이 가능한 수준의 seed를 만들어 보고자 한다. 잘 되야 할텐데...





참조


- X-Mind (free version) 파일 

Front-end Next Generation Stack.xmind

- Angular CLI 

- Angular2 Master Starter Kit

- Ionic2 Seed (*)

- Angular2 Eduction 목록

- Angular2 Awesome 목록

- Angular2 Style Guide - Rangle.io

- Angular2 Code Style Guide - Mgechev

posted by Peter Note
prev 1 next