Gulp

설정 및 설치

  • package.json 생성
{
  "name": "test-front-web",
  "version": "0.0.1.SNAPSHOT",
  "devDependencies": {

  }
}
  • gulp 설치
$ npm install --save-dev gulp 

위의 명령을 실행하고 나면 package.json 파일에 다음과 같이 "gulp": "^3.9.1" 가 추가된 것을 확인할 수 있다.

{
  "name": "test-front-web",
  "version": "0.0.1.SNAPSHOT",
  "devDependencies": {
    "gulp": "^3.9.1"
  }
}

거기에 node_modules 디렉터리가 추가되고 다양한 의존성 라이브러리가 추가되었다.

프로젝트 폴더에 gulpfile.js 를 생성한다. 그리고 그 안에,

// Include gulp
var gulp = require('gulp');

코드를 추가한다.

추가할 수 있는 태스크의 종류는 많지만 그 중에서 몇가지만 소개한다:

  • gulp.task(name, function) - 이름으로 함수를 등록
  • gulp.watch(global, function) - 전역변수의 변경사항이 생겼을 때 호출할 함수 정의
  • gulp.src(global) - 읽어올 위치
  • gulp.dest(folder) - 작성된 파일을 놓을 위치

gulp와 파일 연결하기(Concatenating)

gulp만 설치한다고 끝나는 것은 아니다. gulp 가 동작할 수 있도록 플러그인을 설치하고 gulpfile 에 태스크를 추가해야 한다. gulp-concat 플러그인이 필요하다.

$ npm install --save-dev gulp-concat 

를 실행하고 나면 package.json 에 "gulp-concat": "^2.6.0" 가 추가된다.

이제 gulpfile 에 필요한 테스크를 추가한다.

// Include gulp
var gulp = require('gulp');

// Include plugins
var concat = require('gulp-concat');

//Concatenate JS File: src/js 에 있는 파일들을 main.js 로 연결
gulp.task('scripts', function() {
   return gulp.src('src/js/*.js')
       .pipe(concat('honeymon.js'))
       .pipe(gulp.dest('build/js'));
});

// Default Task
gulp.task('default', ['scripts']);

gulp-concat 플러그인 설정을 포함하고 gulp.task 를 사용하여 기본 테스크에 script 를 추가했다. 이 태스크는 3단계 과정으로 처리가 된다:

  1. gulp.src 에서 정의한 src/js 디렉토리에 있는 확장자 js 를 연결한다.
  2. main.js 로 연결한다.
  3. build/js 디렉토리에 main.js 파일을 밀어 넣는다.

gulp 를 이용한 JS 최소화하기

보통 자바스크립트를 배포할 때 최소화(Minify)하는 과정을 거치는데 gulp 에서는 이를 처리하는 플러그인이 있다. 그리고 나서 파일명 접미사로 .min 를 붙이는 rename 플러그인도 함께 설치한다.

$ npm install --save-dev gulp-unglify gulp-renmae 

이제 gulpfile.js 에 scripts 태스크를 수정한다.

// Include gulp
var gulp = require('gulp');
// Include plugins
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');

//Concatenate JS File: src/js 에 있는 파일들을 main.js 로 연결
gulp.task('scripts', function () {
    return gulp.src('src/js/*.js')
        .pipe(concat('honeymon.js'))
        .pipe(rename({suffix: '.min'}))
        .pipe(uglify())
        .pipe(gulp.dest('js'));
});

gulp 를 이용한 css 처리

gulp 를 이용해서 sass 파일을 컴파일하여 css 를 생성하는 태스크를 추가한다.

루비의 공식적인 sass 컴파일러를 설치한다.

$ npm install --save-dev gulp-ruby-sass 

이제 gulpfile.js 에 sass 태스크를 수정한다.

// Include gulp
var gulp = require('gulp');
// Include plugins
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var sass = require('gulp-ruby-sass');

//Concatenate JS File: src/js 에 있는 파일들을 main.js 로 연결
gulp.task('scripts', function () {
    return gulp.src('src/js/*.js')
        .pipe(concat('honeymon.js'))
        .pipe(rename({suffix: '.min'}))
        .pipe(uglify())
        .pipe(gulp.dest('build/js'));
});

//Compile SASS
gulp.task('sass', function () {
    sass('src/scss/style.scss', {style: 'compressed'})
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest('build/css'));
    sass('src/scss/honeymon/*.scss', {style: 'compressed'})
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest('build/css/honeymon'));
});

// Default Task
gulp.task('default', ['scripts', 'sass']);

프로젝트에 사용하는 이미지 이동

이제 gulp 에서 많은 시간이 걸리는 작업이 남았다. 스크립트나 스타일시트 작업보다 더 오래 걸릴 것이다. gulp-imagemin 와 gulp-cache 를 이용해서 이미지를 최적화하는 작업을 진행한다.

$ npm install --save-dev gulp-imagemin gulp-cache 

gulp-imagemin 와 gulp-cache 에 대한 의존성을 추가하고 image 태스크를 수정하자.

// Include gulp
var gulp = require('gulp');
// Include plugins
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var sass = require('gulp-ruby-sass');
var imagemin = require('gulp-imagemin');
var cache = require('gulp-cache');

//Concatenate JS File: src/js 에 있는 파일들을 main.js 로 연결
gulp.task('scripts', function () {
    return gulp.src('src/js/*.js')
        .pipe(concat('honeymon.js'))
        .pipe(rename({suffix: '.min'}))
        .pipe(uglify())
        .pipe(gulp.dest('build/js'));
});

//Move image files
gulp.task('images', function() {
    return gulp.src(srcPath + '/img/**/*')
        .pipe(cache(imagemin({ optimizationLevel: 5, progressive: true, interlaced: true })))
        .pipe(gulp.dest(buildPath + 'img'));
});

//Compile SASS
gulp.task('sass', function () {
    sass('src/scss/style.scss', {style: 'compressed'})
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest('build/css'));
    sass('src/scss/honeymon/*.scss', {style: 'compressed'})
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest('build/css/honeymon'));
});

//Build JavaScript, Images, Sass
gulp.task('build', ['scripts', 'images', 'sass']);

// Default Task
gulp.task('default', ['build']);

실제로 많이 걸린다..

➜  test-front-web git:(master) ✗ gulp
[14:27:52] Using gulpfile ~/workspace/honeymon/test-front-web/gulpfile.js
[14:27:52] Starting 'scripts'...
[14:27:52] Starting 'images'...
[14:27:52] Starting 'sass'...
[14:27:52] Finished 'sass' after 19 ms
[14:27:52] Finished 'scripts' after 147 ms
[14:27:54] Finished 'images' after 2.18 s
[14:27:54] Starting 'build'...
[14:27:54] Finished 'build' after 1.61 μs
[14:27:54] Starting 'default'...
[14:27:54] Finished 'default' after 1.5 μs

프로젝트에서 작성한 html 을 이동시키자.

html 을 옮기는 과정에서는 2가지 작업을 해야한다.

  • src html 에서 보고 있는 *.css 와 *.js 의 경로를 변경해야 한다.
  • build 로 이동시키면서 빌드 컴파일러된 *.css 와 *.js 를 보도록 변경해야 한다.

우선은 src 에서 build 로 이동처리를 먼저 하자.

// Include gulp
var gulp = require('gulp');
// Include plugins
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var sass = require('gulp-ruby-sass');

var buildPath = 'build/'
var srcPath = 'src/'

//Concatenate JS File: src/js 에 있는 파일들을 main.js 로 연결
gulp.task('scripts', function () {
    return gulp.src(srcPath + 'js/*.js')
        .pipe(concat('honeymon.js'))
        .pipe(rename({suffix: '.min'}))
        .pipe(uglify())
        .pipe(gulp.dest(buildPath + 'js'));
});

//Move image files
gulp.task('images', function() {
    gulp.src(srcPath + 'img')
        .pipe(gulp.dest(buildPath + 'img'));
});

//Compile SASS
gulp.task('sass', function () {
    sass(srcPath + 'scss/style.scss', {style: 'compressed'})
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest(buildPath + 'css'));
    sass(srcPath + 'scss/honeymon/*.scss', {style: 'compressed'})
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest(buildPath + 'css/honeymon'));
});

gulp.task('html-copy', function() {
    gulp.src([srcPath + 'index.html', srcPath + 'sample.html'])
        .pipe(gulp.dest(buildPath))

    gulp.src(srcPath + 'tx/*.html')
        .pipe(gulp.dest(buildPath + '/tx'))
});

//Build JavaScript, Images, Sass
gulp.task('build', ['scripts', 'images', 'sass', 'html-copy']);

// Default Task
gulp.task('default', ['build']);

이제 gulp-html-replace 플러그인을 설치하고 html 을 옮기면서 stylesheet 와 script 를 처리해보자.

$ npm install --save-dev gulp-html-replace

이제 html-copy 테스크에 추가한다.

gulp.task('html-copy', function () {
    //SEE: https://www.npmjs.com/package/gulp-html-replace
    gulp.src([srcPath + 'sample.html'])
        .pipe(htmlReplace({
            css: [
                'css/libs/bootstrap.min.css',
                'css/libs/bootstrap-select.min.css',
                'css/libs/font-awesome/css/font-awesome.min.css',
                'css/style.min.css'
            ],
            js: [
                'js/libs/jquery.min.js',
                'js/libs/bootstrap.min.js',
                'js/libs/bootstrap-select.min.js',
                'js/honeymon.min.js'
            ]
        }))
        .pipe(gulp.dest(buildPath));

    gulp.src([srcPath + 'index.html'])
        .pipe(htmlReplace({
            css: [
                'css/libs/bootstrap.min.css',
                'css/libs/font-awesome/css/font-awesome.min.css',
                'css/libs/bootstrap-select.min.css',
                'css/style.min.css',
                'css/honeymon/index.min.css'
            ],
            js: [
                'js/libs/jquery.min.js',
                'js/libs/bootstrap.min.js',
                'js/libs/bootstrap-select.min.js',
                'js/honeymon.min.js'
            ]
        }))
        .pipe(gulp.dest(buildPath));

    gulp.src(srcPath + 'tx-*.html')
        .pipe(htmlReplace({
            css: [
                'css/libs/bootstrap.min.css',
                'css/libs/font-awesome/css/font-awesome.min.css',
                'css/libs/bootstrap-select.min.css',
                'css/style.min.css',
                'css/honeymon/tx.min.css'
            ],
            js: [
                'js/libs/jquery.min.js',
                'js/libs/bootstrap.min.js',
                'js/libs/bootstrap-select.min.js',
                'js/honeymon.min.js'
            ]
        }))
        .pipe(gulp.dest(buildPath));
});

src 디렉토리 감시하기

이제 src 디렉토리 내에 있는 파일들의 변경사항이 생겼을 때 이를 감지해서 build 태스크를 실행하도록 만들자.

watch 태스크를 생성한다.

gulp.task('watch', function() {
    // Watch .js files
    gulp.watch(srcPath + 'js/*.js', ['scripts']);
    // Watch .scss files
    gulp.watch(srcPath + 'scss/*.scss', ['sass']);
    // Watch image files
    gulp.watch(srcPath + 'images/**/*', ['images']);
});

그 후 기본 태스크에 watch 태스크를 추가한다.

// Include gulp
var gulp = require('gulp');
// Include plugins
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var sass = require('gulp-ruby-sass');
var imagemin = require('gulp-imagemin');
var cache = require('gulp-cache');
var htmlReplace = require('gulp-html-replace');
var cleanCSS = require('gulp-clean-css');

var buildPath = 'build/'
var srcPath = 'src/'

//Concatenate JS File: src/js 에 있는 파일들을 main.js 로 연결
gulp.task('scripts', function () {
    return gulp.src(srcPath + 'js/*.js')
        .pipe(concat('honeymon.js'))
        .pipe(rename({suffix: '.min'}))
        .pipe(uglify())
        .pipe(gulp.dest(buildPath + 'js'));
});

//MOVE libraries
gulp.task('libraries', function () {
    //Copy Javascript
    gulp.src([
        'node_modules/jquery/dist/jquery.min.js',
        'node_modules/bootstrap/dist/js/bootstrap.min.js',
        'node_modules/bootstrap-select/dist/js/bootstrap-select.min.js'])
        .pipe(gulp.dest(buildPath + 'js/libs'));

    //Copy StyleSheet
    gulp.src([
        'node_modules/bootstrap/dist/css/bootstrap.min.css',
        'node_modules/bootstrap-select/dist/css/bootstrap-select.min.css'])
        .pipe(gulp.dest(buildPath + 'css/libs'));

    //Copy font-awesome
    gulp.src(['./node_modules/font-awesome/css/font-awesome.min.css'])
        .pipe(gulp.dest(buildPath + 'css/libs/font-awesome/css'));
    gulp.src(['./node_modules/font-awesome/fonts/*'])
        .pipe(gulp.dest(buildPath + 'css/libs/font-awesome/fonts'));

    //copy bootstrap
});


//Move image files
gulp.task('images', function () {
    return gulp.src(srcPath + '/img/**/*')
        .pipe(cache(imagemin({optimizationLevel: 5, progressive: true, interlaced: true})))
        .pipe(gulp.dest(buildPath + 'img'));
});

//Compile SASS
gulp.task('sass', function () {
    sass(srcPath + 'scss/style.scss', {style: 'compressed'})
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest(buildPath + 'css'));
    sass(srcPath + 'scss/honeymon/*.scss', {style: 'compressed'})
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest(buildPath + 'css/honeymon'));
});

//Replace html js, css
gulp.task('html-copy', function () {
    //SEE: https://www.npmjs.com/package/gulp-html-replace
    gulp.src([srcPath + 'sample.html'])
        .pipe(htmlReplace({
            css: [
                'css/libs/bootstrap.min.css',
                'css/libs/bootstrap-select.min.css',
                'css/libs/font-awesome/css/font-awesome.min.css',
                'css/style.min.css'
            ],
            js: [
                'js/libs/jquery.min.js',
                'js/libs/bootstrap.min.js',
                'js/libs/bootstrap-select.min.js',
                'js/honeymon.min.js'
            ]
        }))
        .pipe(gulp.dest(buildPath));

    gulp.src([srcPath + 'index.html'])
        .pipe(htmlReplace({
            css: [
                'css/libs/bootstrap.min.css',
                'css/libs/font-awesome/css/font-awesome.min.css',
                'css/libs/bootstrap-select.min.css',
                'css/style.min.css',
                'css/honeymon/index.min.css'
            ],
            js: [
                'js/libs/jquery.min.js',
                'js/libs/bootstrap.min.js',
                'js/libs/bootstrap-select.min.js',
                'js/honeymon.min.js'
            ]
        }))
        .pipe(gulp.dest(buildPath));

    gulp.src(srcPath + 'tx-*.html')
        .pipe(htmlReplace({
            css: [
                'css/libs/bootstrap.min.css',
                'css/libs/font-awesome/css/font-awesome.min.css',
                'css/libs/bootstrap-select.min.css',
                'css/style.min.css',
                'css/honeymon/tx.min.css'
            ],
            js: [
                'js/libs/jquery.min.js',
                'js/libs/bootstrap.min.js',
                'js/libs/bootstrap-select.min.js',
                'js/honeymon.min.js'
            ]
        }))
        .pipe(gulp.dest(buildPath));
});

//Watch project
gulp.task('watch', function () {
    // Watch .js files
    gulp.watch(srcPath + 'js/*.js', ['scripts']);

    // Watch .scss files
    gulp.watch([srcPath + '**/*.scss'], ['sass']);
    // gulp.watch(srcPath + 'scss/honeymon/*.scss', ['sass']);

    // Watch image files
    gulp.watch(srcPath + 'img/**/*', ['images']);

    // Watch .html files
    gulp.watch(srcPath + '*.html', ['html-copy']);
});

//Build JavaScript, Images, Sass
gulp.task('build', ['scripts', 'libraries', 'images', 'sass', 'html-copy']);

// Default Task
gulp.task('default', ['build', 'watch']);

이렇게 테스트가 추가되고 나면 src 내에 작은 변화가 생기면 자동적으로 변환이 진행되며 그 결과를 확인할 수 있게 된다.

gulp 동작 실행

gulp 명령어만 실행하면 다음과 같이 build 태스크에 있는 것들이 실행되고 watch 태스크가 실행되면서 디렉토리의 변경사항을 감시하여 변동사항이 생기면 자동으로 빌드가 진행된다.

/usr/local/bin/node /honeymon/node_modules/gulp/bin/gulp.js --color --gulpfile /honeymon//gulpfile.js default
[10:58:15] Using gulpfile ~/workspace/honeymon/test-front-web/gulpfile.js
[10:58:15] Starting 'scripts'...
[10:58:15] Starting 'libraries'...
[10:58:15] Finished 'libraries' after 7.74 ms
[10:58:15] Starting 'images'...
[10:58:15] Starting 'sass'...
[10:58:15] Finished 'sass' after 33 ms
[10:58:15] Starting 'html-copy'...
[10:58:15] Finished 'html-copy' after 14 ms
[10:58:15] Starting 'watch'...
[10:58:15] Finished 'watch' after 56 ms
[10:58:16] Finished 'scripts' after 272 ms
[10:59:31] Starting 'sass'...
[10:59:31] Finished 'sass' after 6.61 ms
[10:59:32] write ./style.css
[11:00:21] Starting 'sass'...
[11:00:21] Finished 'sass' after 5.03 ms
[11:00:22] write ./style.css

참고문헌


'Javascript > Framework & Libs' 카테고리의 다른 글

Error: Cannot find module 'npmlog' 해결  (2) 2016.09.23

IDE 에서 생성한 rebel.xml 이 프로젝트와 맞지 않아서 제대로 되지 않았는데, 이를 해결할 수 있는 방법을 찾았다.

build.gradle 에 아래 스크립트를 추가하면 war 태스크가 실행될 때 war 의존성을 걸어둔 generateRebel 가 호출되면서 build/resources/main 아래에reble.xml 이 생성된다. 프로젝트의 클래스패스와 웹경로의 항목들을 출력하는 특징을 가진다.

이 태스크가 실행되기 위해서는 프로젝트에 war 플러그인이 설치되어 있어야 한다. 

apply plugin: 'war'
// 생략

task generateRebel << {
    def rebelFile = sourceSets.main.output.classesDir.absolutePath + '/rebel.xml'
 
    def srcWebApp = project.webAppDir.absolutePath
    def writer = new FileWriter(rebelFile)
    new groovy.xml.MarkupBuilder(writer).application() {
        classpath{
            dir( name:sourceSets.main.output.classesDir.absolutePath )
        }
        web{
            link(target:'/'){
                dir(name:srcWebApp)
            }
        }
    }
}
war.dependsOn generateRebel
$ ./gradlew build   // or war 만 실행해도 됨
:processResources
:classes
:generateRebel
:war
생성된 rebel.xml
<?xml version="1.0" encoding="UTF-8"?>
<application generated-by="intellij" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.zeroturnaround.com" xsi:schemaLocation="http://www.zeroturnaround.com http://update.zeroturnaround.com/jrebel/rebel-2_1.xsd">
 
<classpath>
<dir name="/Users/honeymon/workspace/prototype-boot/build/classes/main"></dir>  (1)
<dir name="/Users/honeymon/workspace/prototype-boot/src/main/resources"></dir>  (2)
</classpath>
 
</application>

컴파일된 클래스 핫스와핑

변경된 설정파일 모니터링


+ Recent posts