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

Publication

Statistics Graph

Recent Comment

2017.09.04 15:51 JHipster

Angular 최신 버전이 v5 beta-6를 향해 가고 있다. 9월에는 v5 release가 될 것으로 보인다. Angular에서 툴 기능으로 @angular/cli를 제공하고 있는데 오늘은 이것의 내부구조에 대해 연구해 본다. 



@angular/cli 설치 및 프로젝트 생성

설치는 npm 또는 yarn을 이용한다.

$> npm i -g @angular/cli


or 


$> yarn add global @angular/cli


Angular 기반 프로젝트를 생성해 보자.

$> ng new jamong


실행해 보자

$> ng serve




폴더 구조

angular/cli는 Automation Tool 과 Module loader로 webpack을 사용하고 있다. 웹팩의 환경파일을 루트 폴더에 생성한다. 
$> ng eject
=====================================================
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 run build && npm start


// package.json의 build 와 start 스크립트 설정내역

  "scripts": {

    "ng": "ng",

    "start": "webpack-dev-server --port=4200",

    "build": "webpack",

    "test": "karma start ./karma.conf.js",

    "lint": "ng lint",

    "e2e": "protractor ./protractor.conf.js",

    "pree2e": "webdriver-manager update --standalone false --gecko false --quiet"

  },



webpack 오류가 난다면 webpack이  global설치가 않되어 있기때문이다. webpack을 설치한다. 

$> yarn add webpack --dev

또는

$> yarn add global webpack 

또는 

$> npm install -g webpack





Webpack 환경파일

webpack의 기본은 초기 참조할 entry파일과 결과 번들파일을 지정하는 것이다. 

$> webpack <entry file path> <output bundle file path>


예) webpack ./entry.js bunlde.js


간단한 번들링은 CLI를 사용해도 무방하지만 복잡한 옵션이 적용되어야 한다면 환경파일을 사용한다. 예) webpack.config.js 아래 예에서 ouput의 filename에 [name]은 entry의 'app' 키값이다. 

module.exports = {

  context: __dirname + '/app',

  entry: {

    app: './app.js'

  },

  output: {

    path: __dirname + '/dist',

    filename: '[name].bundle.js'

  }

}


환경설정 자세한 옵션은 공식문서를 참조한다. 여기서 주의할 것은 entry는 String, Object, Array로 설정가능하다. 

- String: 하나만 설정

- Array: output 번들링 파일에 순서적으로 합쳐진다.

- Object: SPA처럼 index.html에 적용되는 것이 아니라, index1.html 또는 index2.html 등 output이 각각의 html에 포함될 때 사용한다. 





Webpack Loader

Webpack에는 자바스크립트가 아닌 확장형식의 파일을 자바스크립트에서 동작할 수 있도록 해주는 로더(Loader)가 있다. 즉, 모든(CSS, Images, HTML...)을 모듈로 취급하게 해주는 핵심역할을 로더가 수행한다. 말 그대로 다양한 파일 확장자의 Module Loader의 줄임말이라 보면된다. (전체 목록 참조) 만일 설정중에 module, rules를 사용하지않고 loaders를 쓰거나, options대신 query를 쓰면 webpack 1에 대한 설명이다.


- 스타일: style, css

- 변환: typescript, coffeescript, ES2015


환경파일안에 module 밑으로 설정한다. 


module.exports = {

  entry: ...

  output: ...

  module: {

    rules: [

      {

        test: /\.css$/,

        use: [ 'style-loader', 'css-loader']

      }

    ]

    ...

  }


}


특히 Angular 개발시에는 Typescript를 사용하므로 sourcemap을 남기려면 'source-map-loader'를 module 프로퍼티에 설정한다. (sourcemap에 대해 webpack3에서는 plugin으로 설정도 가능하다.) enforce 설정값을 "pre"로 하면 자바스크립트 변환전에 sourcemap 을 만든다.

{

        "enforce": "pre",

        "test": /\.js$/,

        "loader": "source-map-loader",

        "exclude": [

          /(\\|\/)node_modules(\\|\/)/

        ]

}


개발시에는 Node.js기반의 webpack-dev-server를 통해 개발 페이지를 테스트할 수 있다. 옵션은 --inline (전체 페이지 리로딩) --hot (변경 컴포넌트만 리로딩)한다. 

// 전체 및 부분 리로딩 옵션 설정

$> webpack-dev-server --inline --hot




Webpack Plugins

플러그인은 Output 번들의 Chunk 또는 Compilation 레벨 파일에 대한 추가 작업을 수행한다. 예로 ulgifyJSPlugin은 번들 파일 사이즈를 줄이고, 코드를 못 알아보게 만들어 준다. 또는 extract-text-webpack-plugin의 경우는 css-loader, style-loader의 결과를 하나의 별도 외부 파일로 만들어 준다. (플러그인 목록 참조)


@angular/cli에서  ng eject로 나온 webpack.config.js안의 plugins설정 내역

"plugins": [

    new NoEmitOnErrorsPlugin(),

    new GlobCopyWebpackPlugin({

      "patterns": [

        "assets",

        "favicon.ico"

      ],

      "globOptions": {

        "cwd": path.join(process.cwd(), "src"),

        "dot": true,

        "ignore": "**/.gitkeep"

      }

    }),

    new ProgressPlugin(),

    new CircularDependencyPlugin({

      "exclude": /(\\|\/)node_modules(\\|\/)/,

      "failOnError": false

    }),

    new NamedLazyChunksWebpackPlugin(),

    new HtmlWebpackPlugin({

      "template": "./src/index.html",

      "filename": "./index.html",

      "hash": false,

      "inject": true,

      "compile": true,

      "favicon": false,

      "minify": false,

      "cache": true,

      "showErrors": true,

      "chunks": "all",

      "excludeChunks": [],

      "title": "Webpack App",

      "xhtml": true,

      "chunksSortMode": function sort(left, right) {

        let leftIndex = entryPoints.indexOf(left.names[0]);

        let rightindex = entryPoints.indexOf(right.names[0]);

        if (leftIndex > rightindex) {

          return 1;

        } else if (leftIndex < rightindex) {

          return -1;

        } else {

          return 0;

        }

      }

    }),

    new BaseHrefWebpackPlugin({}),

    new CommonsChunkPlugin({

      "name": [

        "inline"

      ],

      "minChunks": null

    }),

    new CommonsChunkPlugin({

      "name": [

        "vendor"

      ],

      "minChunks": (module) => {

        return module.resource &&

          (module.resource.startsWith(nodeModules) ||

            module.resource.startsWith(genDirNodeModules) ||

            module.resource.startsWith(realNodeModules));

      },

      "chunks": [

        "main"

      ]

    }),

    new SourceMapDevToolPlugin({

      "filename": "[file].map[query]",

      "moduleFilenameTemplate": "[resource-path]",

      "fallbackModuleFilenameTemplate": "[resource-path]?[hash]",

      "sourceRoot": "webpack:///"

    }),

    new CommonsChunkPlugin({

      "name": [

        "main"

      ],

      "minChunks": 2,

      "async": "common"

    }),

    new NamedModulesPlugin({}),

    new AotPlugin({

      "mainPath": "main.ts",

      "replaceExport": false,

      "hostReplacementPaths": {

        "environments/environment.ts": "environments/environment.ts"

      },

      "exclude": [],

      "tsConfigPath": "src/tsconfig.app.json",

      "skipCodeGeneration": true

    })

]


JHipster로 자동생된 webpack.config.dev.js의 plugins 설정 내역

plugins: [

        new BrowserSyncPlugin({

            host: 'localhost',

            port: 9000,

            proxy: {

                target: 'http://localhost:9060',

                ws: true

            }

        }, {

            reload: false

        }),

        new webpack.NoEmitOnErrorsPlugin(),

        new webpack.NamedModulesPlugin(),

        new writeFilePlugin(),

        new webpack.WatchIgnorePlugin([

            utils.root('src/test'),

        ]),

        new WebpackNotifierPlugin({

            title: 'JHipster',

            contentImage: path.join(__dirname, 'logo-jhipster.png')

        })

 ]




Production vs Development

개발과 운영 시점에 webpack 환경을 달리 적용하기 위해 보통  webpack.config.dev.js 와 webpack.config.prod.js를  따로 만들고 package.json의 script에 적용해 사용한다. package.json에 적용하고 싶지 않다며 gulp를 사용해도 된다. 


@angular/cli의 script 내역

 "scripts": {

    "ng": "ng",

    "start": "webpack-dev-server --port=4200",

    "build": "webpack",

    "test": "karma start ./karma.conf.js",

    "lint": "ng lint",

    "e2e": "protractor ./protractor.conf.js",

    "pree2e": "webdriver-manager update --standalone false --gecko false --quiet"

}


JHipster script 내역

"scripts": {

    "lint": "tslint --type-check --project './tsconfig.json' -e 'node_modules/**'",

    "lint:fix": "yarn run lint -- --fix",

    "ngc": "ngc -p tsconfig-aot.json",

    "cleanup": "rimraf target/{aot,www}",

    "clean-www": "rimraf target//www/app/{src,target/}",

    "start": "yarn run webpack:dev",

    "serve": "yarn run start",

    "build": "yarn run webpack:prod",

    "test": "karma start src/test/javascript/karma.conf.js",

    "test:watch": "yarn test -- --watch",

    "webpack:dev": "yarn run webpack-dev-server -- --config webpack/webpack.dev.js --progress --inline --hot --profile --port=9060",

    "webpack:build:main": "yarn run webpack -- --config webpack/webpack.dev.js --progress --profile",

    "webpack:build": "yarn run cleanup && yarn run webpack:build:main",

    "webpack:prod:main": "yarn run webpack -- --config webpack/webpack.prod.js --progress --profile",

    "webpack:prod": "yarn run cleanup && yarn run webpack:prod:main && yarn run clean-www",

    "webpack:test": "yarn run test",

    "webpack-dev-server": "node --max_old_space_size=4096 node_modules/webpack-dev-server/bin/webpack-dev-server.js",

    "webpack": "node --max_old_space_size=4096 node_modules/webpack/bin/webpack.js",

    "e2e": "protractor src/test/javascript/protractor.conf.js",

    "postinstall": "webdriver-manager update && node node_modules/phantomjs-prebuilt/install.js"

}


to be continued...



<참고>

- Webpack core concept

- 네이버 webpack 소개

- Webpack의 혼란스러운 사항들

- Webpack3에서 주의할 점


신고

'JHipster' 카테고리의 다른 글

[CLI] @angular/cli속의 Webpack 이해하기  (0) 2017.09.04
posted by peter yun 윤영식
2017.04.23 15:51 Angular/Concept

Angular CLI를 통해 프로젝트를 생성하고 Docker에 Nginx를 띄워서 간단히 연결해 보자. 




Angular CLI 기반 프로젝트 생성


NodeJS버전은 6최신을 사용한다. 

$ npm install -g @angular/cli 


설치가 되었다면 ng 명령을 통해 프로젝트를 생성한다. 

$ ng new angular-docker


프로젝트가 생성되었으면 프로젝트 폴더로 이동해서 소스를 빌드한다. 

$ cd angular-docker

$ ng build

Hash: cfba09939df99de45615

Time: 7424ms

chunk    {0} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 165 kB {4} [initial] [rendered]

chunk    {1} main.bundle.js, main.bundle.js.map (main) 3.61 kB {3} [initial] [rendered]

chunk    {2} styles.bundle.js, styles.bundle.js.map (styles) 9.77 kB {4} [initial] [rendered]

chunk    {3} vendor.bundle.js, vendor.bundle.js.map (vendor) 2.09 MB [initial] [rendered]

chunk    {4} inline.bundle.js, inline.bundle.js.map (inline) 0 bytes [entry] [rendered]





Docker CE 기반 Nginx 관리


Docker를 잘 모른다면 Docker CE를 설치해 사용한다. 

  - download docker CE (Community Edition)

 - Mac 버전을 설치하면 Docker 가 기동이 된다.

 

     


다음으로 Nginx image 를 docker명령을 통해 내려받는다. 만일 사용하지 않는 Docker image들이 있다면 다 삭제를 한고 작업을 해보자.

// Delete all docker containers

$ docker rm $(docker ps -a -q)


// Delete all docker images

$ docker rmi $(docker images -q)


// Install docker image

$ docker pull nginx

Using default tag: latest


// 설치 내역 확인

$ docker images 

REPOSITORY        TAG                 IMAGE ID            CREATED             SIZE

nginx                  latest              5766334bdaa0   2 weeks ago         183 MB


Angular 빌드 폴더로 이동해서 Nginx를 수행한다. 

$ cd dist

$ docker run -d -p 8080:80 -v $(pwd):/usr/share/nginx/html nginx:latest

48db2f0626c5a10429e95cbbbaf3cc58769cda45a9c1e7084b4f3a260e576838


// 이미지 실행 확인

$ docker ps -a

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                           NAMES

48db2f0626c5        nginx:latest        "nginx -g 'daemon ..."   2 minutes ago       Up 2 minutes        443/tcp, 0.0.0.0:8080->80/tcp   loving_lumiere


수행되고 있는 이미지를 멈추고 제거해 보자. stop, rm 다음은 Container ID의 처음 두자를 입력한다. 

// 멈춤 

$ docker stop 48

48


// 제거

$ docker rm 48

48


// 확인

$ docker ps -a

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES


Kinetic 애플리케이션을 사용해서 CLI 명령과 동일하게 GUI 기반으로 Container를 관리할 수 있다.




Docker Compose 사용하기


컴포즈는 환경을 기반으로 다양한 도커 이미지들을 동시에 기동하고 연결하는 역할을 수행한다. Nginx, NodeJS, MongoDB등을 서로 다른 Docker image기반으로 기동하고 연결하는 환경설정을 docker_compose.yml에 한다. angular-seed 예는 다음과 같다. 

version: '2'


services:


  angular-seed:

    build:

      context: .

      dockerfile: ./.docker/angular-seed.development.dockerfile

    command: npm start

    container_name: angular-seed-start

    image: angular-seed

    networks:

      - dev-network

    ports:

      - '5555:5555'


networks:

  dev-network:

    driver: bridge


빌드하고 수행하기 

$ docker-compose build

$ docker-comopse up


ng-conf 2017 의 docker 이야기




<참조>



신고
posted by peter yun 윤영식
2017.04.11 20:40 Reactive Realtime

RethinkDB는 리얼타임 웹을 위한 NoSQL 저장소이다. 




설치하기


가이드에 따라 OS에 맞게 설치한다. (맥기준)

$ brew update && brew install rethinkdb

또는 

다운로드 (.dmg)


docker로 실행할 경우

$ docker run -d -P --name rethink1 rethinkdb


저장소를 설치했으면 다음으로 NodeJS에서 사용할 클라이언트 드라이버를 설치한다. 




실행하기


설치확인

$ which rethinkdb

/usr/local/bin/rethinkdb


실행하기

$ rethinkdb --bind all

Running rethinkdb 2.3.5 (CLANG 7.3.0 (clang-703.0.31))...

Running on Darwin 16.5.0 x86_64

Loading data from directory /Users/dowonyun/opensource/rethinkdb_data

Listening for intracluster connections on port 29015

Listening for client driver connections on port 28015

Listening for administrative HTTP connections on port 8080


브라우져기반 Admin(http://localhost:8080)을 통해 실시간 변경사항 조회, 테이블 생성, 서버관리, 데이터 조회등을 할 수 있다.




NodeJS환경에서 RethinkDB 접속하기


npm으로 노드환경을 만들고 rethink driver를 설치한다. 

$ npm init -y

$ npm i rethinkdb --save


신규 파일을 만들고 Connect를 하고, 기본 데이터베이스인 test안에 신규 테이블을 생성해 보자. 

// connect.js

r = require('rethinkdb');


let connection = null;

r.connect({ host: 'localhost', port: 28015 }, function (err, conn) {

    if (err) throw err;

    connection = conn;

    

    r.db('test').tableCreate('authors').run(connection, function (err, result) {

        if (err) throw err;

        console.log(JSON.stringify(result, null, 2));

    })

})


실행을 해보면 테이블이 생성되고 Admin화면에서도 확인해 볼 수 있다. rethinkDB 또한 Shard, Replica를 제공함을 알 수 있다. 

$ node connect.js

{

  "config_changes": [

    {

      "new_val": {

        "db": "test",

        "durability": "hard",

        "id": "05f4b262-9e01-477e-a74c-3d4ccb14cf84",

        "indexes": [],

        "name": "authors",

        "primary_key": "id",

        "shards": [

          {

            "nonvoting_replicas": [],

            "primary_replica": "DowonYunui_MacBook_Pro_local_bcb",

            "replicas": [

              "DowonYunui_MacBook_Pro_local_bcb"

            ]

          }

        ],

        "write_acks": "majority"

      },

      "old_val": null

    }

  ],

  "tables_created": 1

}


다음으로 rethinkDB는 자체 query 엔진을 가지고 있고, rethinkDB를 위한 쿼리 언어를 ReQL이라 한다. ReQL의 3가지 특성은 다음과 같다. 

  - ReQL embeds into your programming language: 펑션으로 만들어짐

  - All ReQL queries are chainable: Dot ( . ) 오퍼레이터를 통해 체이닝 메소드 호출이다. 

  - All queries execute on the server: run을 호출해야 비로서 쿼리를 수행한다.


예제는 3가지의 특성을 보여주고 있다. query를 json 또는 SQL query statement으로 짜는게 아니라. 메소드 체이닝을 통해 쿼리를 만들고, 맨 나중에 Connection 객체를 파라미터로 넘겨주면서 run() 메소드를 실행한다. 

r.table('users').pluck('last_name').distinct().count().run(conn)




일반 SQL 문과 자바스크립트 기반의 ReQL 차이점


구문의 차이저을 보자. row가 document이고, column이 field라는 차이점만 존재한다. 


 Insert


Select



다른 예제는 가이드 문서를 참조하자.




Horizon을 이용한 클라이언트 & 서버 구축하기


Horizon은 rehtinkDB를 사용해 realtime서비스 개발을 돕는 Node.js기반의 서버 프레임워크이면서 클라이언트에서 서버단의 접속을 RxJS 기반의 라이브러리를 통해 가능하다. 마치 Meteor 플랫폼과 유사한 리얼타임 아키텍트를 제공한다. Horizon의 CLI를 글로벌로 설치한다.

$ npm install -g horizon


호라이즌 실행은 hz 이다. 애플리케이션 스켈레톤을 hz을 이용해 만든다.

$ hz init realtime_app

Created new project directory realtime_app

Created realtime_app/src directory

Created realtime_app/dist directory

Created realtime_app/dist/index.html example

Created realtime_app/.hz directory

Created realtime_app/.gitignore

Created realtime_app/.hz/config.toml

Created realtime_app/.hz/schema.toml

Created realtime_app/.hz/secrets.toml


hz 서버 구동하고 http://localhost:55584/ 로 접속하면 http://localhost:8080 접속화면과 동일한 Admin화면을 볼 수 있다.

$ hz serve --dev

App available at http://127.0.0.1:8181

RethinkDB

   ├── Admin interface: http://localhost:55584

   └── Drivers can connect to port 55583

Starting Horizon...

🌄 Horizon ready for connections


http://127.0.0.1:8181/을 호출하면 샘플 웹 화면을 볼 수 있다. 보다 자세한 사항은 홈페이지를 참조하고, 차후에 다시 다루어 보기로 하자.




<참조>

  - rethinkDB 10분 가이드

  - ReQL 가이드

  - Pluralsight 가이드

신고

'Reactive Realtime' 카테고리의 다른 글

[RethinkDB] 시작하기  (0) 2017.04.11
[Flux] Flux 배우는 방법  (0) 2015.07.04
posted by peter yun 윤영식
2017.04.04 10:59 Dev Environment/Build System

Gulp 빌드 환경에 파일이 변경되었을 때 자동으로 브라우져 화면을 업데이트해주는 Live reload환경을 접목해 본다.





Gulp 환경 만들기


gulp CLI를 설치한다.

$ npm i -g gulp-cli


npm 대신 속도가 빠르다는 yarn을 사용해 본다. yarn을 설치한다.

$ npm i -g yarn



테스트 폴를 생성하고,yarn을 이용해 package.json을 만든다. -y 플래그를 주면 모두 Yes로 응답해서 package.json을 생성해준다.

$ mkdir livereload && cd livereload

$ yarn init -y

yarn init v0.21.3

warning The yes flag has been set. This will automatically answer yes to all questions which may have security implications.

success Saved package.json

✨  Done in 0.06s.



index.html파일을 생성하고, gulp 패키지를 로컬에 설치한다. index.html에 간단한 body 태그를 넣는다. 

$ touch index.html

$ yarn add --dev gulp


TypeScript기반으로 파일을 작성하기 위해 다음 설정을 한다. [Typescript] NodeJS에서 Typescript 사용하기

$ yarn add --dev @types/node



gulp환경파일을 생성하고, default 태스크를 작성한다. gulp 명령을 실행하면 default 태스크가 실행된다.

$ touch Gulpfile.ts


// Gulpfile.js

const gulp = require('gulp');


gulp.task('default', function () {

  console.log('Gulp and running!')

});


// test

$ gulp

[09:27:23] Using gulpfile ~/prototyping/livereload/gulpfile.ts

[09:27:23] Starting 'default'...

Gulp and running!

[09:27:23] Finished 'default' after 71 μs





테스트 서버 환경 만들기


Express를 설치하고 정적 파일을 처리하는 서버를 생성한다.

$ yarn add --dev express


// Gulpfile.ts

const gulp = require('gulp');


function startExpress() {

  const express = require('express');

  const app = express();

  app.use(express.static(__dirname));

  app.listen(4000);

}


gulp.task('default', () => startExpress());


index.html 을 작성하고, gulp 명령을 수행한 다음 http://localhost:4000 호출해서 hi peter가 출력하면 정상작동이다. 

<!DOCTYPE html>

<html>

  <head>

    <meta charset="utf-8">

    <title></title>

  </head>

  <body>

    hi peter

  </body>

</html>


다음으로 livereload server 인 tiny-lr을 설치한다.

$ yarn add --dev tiny-lr


tiny-lr서버도 gulp환경에 넣는다. gulp명령을 실행하고 http://localhost:35729/ 접속해서 {"tinylr":"Welcome","version":"1.0.3"} 출력되면 정상작동이다. tiny-lr의 기본 포트는 35729 이다.

const gulp = require('gulp');


function startExpress() {

  const express = require('express');

  const app = express();

  app.use(express.static(__dirname));

  app.listen(4000);

}


function startLivereload() {

  const lr = require('tiny-lr')();

  lr.listen(35729);

}


gulp.task('default', () => {

  startExpress();

  startLivereload();

});





Livereload 환경 만들기


전체 동작방식은 다음과 같다.

  - 브라우져가 열리면 livereload.js는 tiny-lr과 웹소켓 연결을 맺는다.

  - 1) gulp.watch가 파일 변경을 감지한다. 

  - 1) gulp.watch는 변경파일에 대해 tiny-lr에게 reload 하라고 호출한다. 

  - 2) tiny-lr 서버는 livereload.js 모듈과 웹소켓으로 통신한다.

  - 3) livereload.js는 파일을 다시 요청한다. 

  - 화면이 refresh되면서 livereload.js와 tiny-lr 간 웹소켓 연결을 다시 맺는다. 





Express로 서비스하는 페이지가 livereload 처리하는 자바스크립트 로직을 넣기위해 connect-livereload NodeJS 미들웨어도 설치한다.

$ yarn add --dev connect-livereload


connect-livereload를 Express 미들웨어로 설정한다.

// Gulpfile.ts

function startExpress() {

  const express = require('express');

  const app = express();

  app.use(require('connect-livereload')());

  app.use(express.static(__dirname));

  app.listen(4000);

}



gulp.watch를 통해 변경된 파일의 목록을 tiny-lr에 전달하는 코드를 작성한다. 

const gulp = require('gulp');


function startExpress() {

  const express = require('express');

  const app = express();

  app.use(require('connect-livereload')());

  app.use(express.static(__dirname));

  app.listen(4000);

}


let lr;

function startLivereload() {

  lr = require('tiny-lr')();

  lr.listen(35729);

}


function notifyLivereload(event) {

  // `gulp.watch()` events 는 절대경로를 주기 때문에 상대 경로(relative)를 만든다.

  var fileName = require('path').relative(__dirname, event.path);


  lr.changed({

    body: {

      files: [fileName]

    }

  });

}


gulp.task('default', () => {

  startExpress();

  startLivereload();

  gulp.watch('*.html', notifyLivereload);

});


다시 gulp를 수행하고 브라우져에서 http://localhost:4000/index.html 을 호출한 후에 index.html의 내용을 변경하면 브라우져가 자동으로 refresh되는 것을 볼 수 있다. 브라우져에서 element검사를 하면 아래와 같이 livereload.js파일이 </body> 전에 자동 추가된다. (소스 참조)



위의 코드를 단순히 하기위해 gulp-livereload를 사용할 수도 있다. 샘플 파일: https://github.com/BISTel-MIPlatform/livereload-tiny-lr





참조

  - https://github.com/mklabs/tiny-lr

 - https://github.com/livereload/livereload-js

  - https://github.com/intesso/connect-livereload

  - https://github.com/vohof/gulp-livereload

신고
posted by peter yun 윤영식
2017.04.03 16:07 Dev Environment

오래된 Grunt명령을 수행 결과를 디버깅할 일이 생겨서 MS Code에서 시도해 보기로 했다. 디버깅을 위한 설정방법을 알아보자. 



설정열기


먼저 MS Code의 Debug화면으로 이동한후 설정(하단 톱니바퀴)을 클릭한다.


설정을 클릭하면 launch.json 파일이 자동으로 열린다. launch.json파일은 MS Code가 오픈하고 있는 폴더의 최상위에 .vscode 폴더밑에 존재한다. 이곳에 Grunt  디버깅용 환경설정을 추가한다. 




환경설정


launch.json파일안에 다음과 같이 추가한다. 

  - node 타입이고, launch 한다. 

  - name: 디버깅창의 목록에 표시될 이름

  - args: grunt <argument> 명령

  - program: grunt 파일 위치

  - stopOnEntry: 시작한 프로그램에서 breakpoint가 없어도 시작 프로그램에서 중단점을 자동으로 시작할지 여부

  - cwd: 현재 디렉토리, 파일 참조하는 최상위 폴더 위치

"configuration": [

    {

            "type": "node",

            "request": "launch",

            "name": "Grunt Directly",

            "args": ["serve"],            

            "program": "/Users/peter/.nvm/versions/node/v6.10.1/bin/grunt", 

            "stopOnEntry": true,

            "cwd": "${workspaceRoot}"

      },

...

]





디버깅


이제 grunt task파일을 디버깅해보자. 

  - 먼저 디버깅 중단점(break point)를 설정한다. 소스 에디터에서 좌측의 라인 번호 옆 공간을 클릭해서 설정한다. 클릭할 때 빨간점이 찍힌다.

  - 좌측 상단에서 grunt 디버깅 설정한 명칭 "Grunt Directly"를 선택한다. 

  - 실행 (녹색 삼각형 버튼)을 클릭한다.

  - 중단점에 실행이 멈추면서 우측 상단에 "debugging step"바가 나오고 실행, over, into, 멈춤을 통해 소스를 디버깅할 수 있다. 

 



상세 설정 정보는 MS Code 가이드를 참조하자.


Happy, Enjoy Coding~~~


신고

'Dev Environment' 카테고리의 다른 글

[MS Code] Grunt 명령 디버깅하기  (0) 2017.04.03
Aptana + Spket 개발환경 구축하기  (0) 2012.11.23
posted by peter yun 윤영식