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

Publication

Statistics Graph

Recent Comment

2017.11.15 16:31 Meteor/Angular + Meteor v1.6

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 yun 윤영식
2017.11.08 17:20 Meteor/Angular + Meteor v1.6

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 환경설정 요약



신고
posted by peter yun 윤영식

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 yun 윤영식
prev 1 next