최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday

티스토리 뷰


   [ GRUNT ]



Grunt 란 : task 단위의 command line 을 통해 동작하는 자바스크립트용 빌드 툴 ( 더 자세히 알기 클릭 )



이 글에서 사용할 Grunt 기능 : js, css 파편화를 모두 합치고(concat), 간결화하며(uglify),  압축한다(minifying)



Grunt 로 얻을수 있는 잇점 : compile build된 결과물처럼 파일을 얻을수 있기때문에

   

                                    웹 패키지 배포를 자동화 툴을 사용하여 손쉽게 구축할 수 있다.




   Grunt 를 설치하기 전에 준비해야할 폴더및 파일


Grunt를 실제 실행해 보기위한 샘플 코드가 필요한데 


본인의 경우 D 드라이브 바로 아래에 GRUNT 라는 폴더를 만들고 아래와 같이 폴더를 구성하였다


D:\>GRUNT


참고로 아래에있는 예제 소스작성 혹은 붙여넣기가 번거로운 경우 아래 GRUNT.zip 파일을 다운받아 폴더를 구성하도록 하고 


실제 Grunt 툴을 사용함에 있어서 주의깊에 살펴볼 폴더는 build 에 생성되는 결과물이다.


GRUNT.zip


# D > GRUNT 폴더구성


  아래와같이 build, css, js, log, after.html, before.html 을 만든다.



# D > GRUNT 폴더 > before.html 


( 아래 나열된 소스코드를 전부 입력, 혹은 붙여넣기 하거나 GRUNT.zip파일을 다운받아 압축풀었다면 ) 


먼저 before.html을 실행하면 Grunt 툴을 이용하기 이전의 결과물을 확인할 수 있다.


각각 test_1.css, test_2.css, test_1.js, test_2.js 를 이용하여 화면을 출력하고 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
 
    <link rel='stylesheet' href='css/test_1.css' />
    <link rel='stylesheet' href='css/test_2.css' />
    <title>Document</title>
</head>
<body>
 
    <script src='js/test_1.js'></script>
    <script src='js/test_2.js'></script>
</body>
</html>
 
cs



# D > GRUNT 폴더 > after.html


( 실제로 Grunt 를 모두 설치하고 나서 최종적으로 다시 실행할 html 이다 )


아직 실제 파일은 없지만 css는 style.css 이름으로 js는 built.min.js 이름으로 바꾸어서 


미리 after.html 을 만들어 둔다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
 
    <link rel='stylesheet' href='build/styles.css' />
    <title>Document</title>
</head>
<body>
    <span class='sass'>sass color is orange!</span>
    <script src='build/built.min.js'></script>
</body>
</html>
 
cs



# D > GRUNT > css 폴더 > test_1.css


1
2
3
4
body{
    background-color: #eee;
}
 
cs



# D > GRUNT > css 폴더 > test_2.css


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
h2{
    color:blue;
    font-weight: 800;
}
h3{
    color:blue;
    font-weight: 400;
}
h4{
    color:blue;
    font-weight: 200;
}
 
 
cs




# D > GRUNT > js 폴더 > test_1.js


1
2
3
4
var newH1 = document.createElement("H1");
newH1.innerHTML = "test_1.js 에서 추가된 H1 입니다.";
document.body.appendChild(newH1);
 
cs



# D > GRUNT > js 폴더 > test_2.js


1
2
3
4
5
6
7
8
9
10
11
var newH2 = document.createElement("H2");
newH2.innerHTML = "test_2.js 에서 추가된 H2 입니다.";
document.body.appendChild(newH2);
 
var div;
for(var i=0; i<10; i++){
    div = document.createElement("div");
    div.innerHTML = i.toString();
    document.body.appendChild(div);
}
 
cs





# D > GRUNT > js 폴더 > errorToDo.js


   JSHint 플러그인 실습을 위해서 아래에 있는 에러코드가 포함된 js 를 넣어놓는다.


   D:\>GRUNT>js>errorToDo.js


1
2
"일부러 발생시킨 에러" + string;
 
cs



# D > GRUNT > js 폴더 > etc폴더 > errorToDo.js

  

   JSHint 플러그인 실습을 위해서 아래에 있는 에러코드가 포함된 js 를 넣어놓는다.


   D:\>GRUNT>js>etc>errorToDo.js  


1
2
"일부러 발생시킨 에러" + string;
 
cs



# D > GRUNT > log 폴더 > grunt_compiled 폴더


  js가 제대로 compile 되었는지 로그로 남기기위한 폴더를 만들어 둔다.


  D:\>GRUNT>log>grunt_compiled


(폴더만 생성하도록 한다)




자, 여기까지 준비가 되었다면 실제로 grunt 테스트할 준비가 모두 완료되었다.




   Grunt 설치



1. 먼저 NodeJS 설치유무와 버전을 확인한다.



반드시 관리자권한으로 실행한 명령 프롬프트에서 다음 명령어를 실행한다.


> node -v 


nodejs 가 설치되어 있는지 확인함과 동시에 버전을 알려주는데 현재 이 글에서는 6.10.3 이상을 기준으로 설명하도록 하겠다.





2. Grunt CLI 설치 



커맨드라인으로 실행할 수 있는 인터페이스를 다음의 명령어로 설치한다. ( 참조 : https://github.com/gruntjs/grunt-cli )


> npm install -g grunt-cli 


여기서 -g 옵션은 어떤 폴더상에 위치해 있던지 전역적으로 명령 호출이 가능한 globally 옵션이다.


(Install this globally and you'll have access to the grunt command anywhere on your system.)





3. Grunt 를 사용할 폴더로 이동하여 Grunt 설치


앞서서 만들었던 D:\>GRUNT 폴더로 이동한다. 본인의 경우 D 드라이브 바로 밑에 GRUNT 폴더를 생성하였으므로


C:\> 드라이브에서 명령어 D: 를 입력하여 D 드라이브로 이동하였다.


( 참고로 드라이브 이동은 cd 명령이 아닌 C: D: E: 처럼 드라이브명 + 콜론으로 입력한다. )


드라이브가 이동된 이후에 GRUNT가 만들어진 폴더를 cd 명령어를 사용하여 이동하도록 한다.



이후 앞으로의 모든 플러그인 설치와 실행은 D\GRUNT> 경로상에서 이루어지며


아래 명령어를 실행하여 Grunt를 설치한다.


> npm install grunt --save-dev



--save-dev 옵션은 package.json 파일과 연동되어 파일 내부의 의존성(devDependencies)항목에 자동으로 추가해준다.


설치가 완료되면 GRUNT > node_modules 라는 패키지가 자동으로 설치되어있을것이다.





   package.json 파일생성하기



package.json 은 node.js로 프로젝트를 진핼할때 npm install 모듈명 으로 패키지를 설치하고 사용하게되는데 


이때 이런 정보를 담고있는 json 파일이다.


package.json 을 처음 작성할때 다음의 명령을 입력한다.


> npm init


을 실행하면 name 부터 입력을 받는 질문이 표시된다.


name, description 정도만 입력하고 특별한 코멘트가 없는경우 엔터키로 skip 한다.






   Gruntfile.js 생성하기


GRUNT 폴더에 Gruntfile.js 를 아래와 같은 형식으로 만들어 둔다.


7번 라인 : 앞으로 사용할 패키지들을 설치하여 사용할것이고


13, 16 번 라인 : 설치된 패키지들을 호출할 것이다.


GRUNT > Gruntfile.js


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module.exports = function(grunt) {
 
    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        
        package:{ //여기에 패키지들이 적용된다.
        }
        
    });
 
    //Gruntfile 내에서 자바스크립트의 코드로 아래의 명령을 사용
    grunt.loadNpmTasks('full-package-name');
 
    //grunt 명령어로 실행할 작업
    grunt.registerTask('default', ['package-name']);
 
};
 
cs




   concat 플러그인 설치


grunt-contrib-concat : File 통합 플러그인


ㄱ. concat 을 설치한다.


> npm install grunt-contrib-concat --save-dev 



--save-dev 옵션으로 설치하였기 때문에 package.json 에 다음과같이


"devDependencies": {

    "grunt-contrib-concat": "^1.0.1",

.... 으로 자동으로 플러그인명과 버전이 등록될 것이다.


Tip! > npm uninstall grunt-contrib-concat --save-dev 하면 package.json 에서 자동으로 플러그인명이 삭제될 것이다.



ㄴ. Gruntfile.js 작성.


GRUNT > Gruntfile.js 에서 다음과 같이 입력한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
module.exports = function(grunt) {
 
    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        
         concat:{
            options: {
                stripBanners:  true,
                separator: ';',
                banner: '/* <%= pkg.name %> - v<%= pkg.version %> - '+'<%= grunt.template.today("yyyy-mm-dd") %> */',  //동작 시점의 날짜가 출력
                footer : "",
                
                
            },
            
            dist:{
                src:['js/test_1.js','js/test_2.js'],
                dest:'build/built.js'
            },
            
            // Invalid or Missing Files Warning 잘못 또는 누락된 파일 경고 : 해당파일이 없거나 유효하지 않으면 경고
            missing:{
                src:['log/grunt_compiled'],
                dest: 'log/grunt_compiled/compiled.log',
                nonull: true
            }
            
            /*
            //Multiple targets 별도의 설정을 두개지정하고 다중작업
            //basic 구성
            basic: { 
                src: ['js/test_1.js', 'js/test_2.js'], 
                dest: 'build/basic.js', 
            }, 
            // extras
            extras: { 
                src: ['js/test_1.js', 'js/test_2.js'], 
                dest: 'build/extras.js', 
            },
            */
 
            
        }
    });
 
    //Gruntfile 내에서 자바스크립트의 코드로 아래의 명령을 사용
    grunt.loadNpmTasks('grunt-contrib-concat');
 
    //grunt 명령어로 실행할 작업
    grunt.registerTask('default', ['concat']);
};
cs



concat 플러그인을 사용하기 위해 concat 객체를 정의하고 그 안에 세부적인 옵션들을 정의하여 파일을 통합할수 있다.


options : 


dist :


missing :


ㄷ. grunt 실행


> grunt 를 실행해 보면




아래와 같이 test_1.js 와 test_2.js 가 build/build.js 로 합쳐져있다.




missing 옵션으로 사용한 src와 dest 파일지정으로 log 옵션으로 사용하였는데 제대로 생성됨을 확인.



   uglifyJS


grunt-contrib-uglify : 공백및 줄바꿈에대한 압축실행


ㄱ. 설치


> grunt-contrib-uglify --save-dev





ㄴ. Gruntfile.js 작성 (기존의 내용은 지우고 이 내용으로 작성하여 테스트 하도록한다.)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
module.exports = function(grunt) {
 
    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
 
        uglify:{
            options: {
                mangle: false//변수와 함수 이름을 변경되는 것을 방지할경우 false 사용
                compress: {
                    drop_console: true //콘솔경고해제
                },
                //beautify: true // 디버깅이나 문제해결을 위해 사용
            },
            build: {
                src: 'build/built.js',
                dest: 'build/built.min.js'
            }
        }
    });
 
    //Gruntfile 내에서 자바스크립트의 코드로 아래의 명령을 사용
    grunt.loadNpmTasks('grunt-contrib-uglify');
 
    //grunt 명령어로 실행할 작업
    grunt.registerTask('default', ['uglify']);
    
};
cs


ㄷ. 실행


> grunt




결과 ) 위에서 합쳐졌던 build.js 가 build.min.js 로 변환되었다




   JSHint


jsHint : 자바스크립트 코드 검사


ㄱ. 설치


> grunt-contrib-jshint --save-dev




ㄴ. Gruntfile.js 작성


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
module.exports = function(grunt) {
 
    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
 
        jshint:{
            //all: ['Gruntfile.js', 'js/test_01.js', 'js/test_02.js'] // 기본적으로 자기자신을 포함하고, 직접 지정해서 사용
            //all: ['js/*'] // 혹은 js 폴더의 모든 파일을 검사
            //all: ['js/etc/*.js'] //측정폴더의 모든 js 검사
            all:['js/*'],
            options:{
                force: true// true로 설정시 error 가 있다하더라도 fail 시키지않고 계속 진단
                //reporter: require('jshint-stylish')
            }
        }
    });
 
    //Gruntfile 내에서 자바스크립트의 코드로 아래의 명령을 사용
    grunt.loadNpmTasks('grunt-contrib-jshint');
 
    //grunt 명령어로 실행할 작업
    grunt.registerTask('default', ['jshint']);
 
};
 
cs



ㄷ. 실행





플러그인 유틸인 jshint-stylish 설치 :  output을 modifying 할 수 있는 옵션 유틸


> npm install jshint-stylish --save-dev




 Gruntfile.js 재작성


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
module.exports = function(grunt) {
 
    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
 
        jshint:{
            //all: ['Gruntfile.js', 'js/test_01.js', 'js/test_02.js'] // 기본적으로 자기자신을 포함하고, 직접 지정해서 사용
            //all: ['js/*'] // 혹은 js 폴더의 모든 파일을 검사
            //all: ['js/etc/*.js'] //측정폴더의 모든 js 검사
            all:['js/*'],
            options:{
                force: true// true로 설정시 error 가 있다하더라도 fail 시키지않고 계속 진단
                reporter: require('jshint-stylish')
            }
        }
    });
 
    //Gruntfile 내에서 자바스크립트의 코드로 아래의 명령을 사용
    grunt.loadNpmTasks('grunt-contrib-jshint');
 
    //grunt 명령어로 실행할 작업
    grunt.registerTask('default', ['jshint']);
 
};
 
cs


실행하여 위의 이미지와 같이 에러결과가 파란색으로 표시된다.





   cssmin


cssmin : css 공백및 줄바꿈에대한 압축실행


ㄱ. 설치


> npm install grunt-contrib-cssmin --save-dev



ㄴ. Gruntfile.js 작성


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
module.exports = function(grunt) {
 
    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
 
        cssmin:{
            minify:{
                expand: true,
                cwd: "css/"// css 폴더 위치
                src:['*.css''!*.min.css'], // 파일지정, 이때 .min.css 는 제외한다.
                dest:'build'// 출력폴더 지정
                ext:".min.css" // 확장자 지정
            },
            options:{
                keppSpecialComments: 0 //  default : '!' 가 붙은 주석 보존, 1 : '!' 가 붙은 주석 중 첫번째 주석만 보존, 0 : 모든 주석 제거
            }
        }
    });
 
    //Gruntfile 내에서 자바스크립트의 코드로 아래의 명령을 사용
    grunt.loadNpmTasks('grunt-contrib-cssmin');
 
    //grunt 명령어로 실행할 작업
    grunt.registerTask('default', ['cssmin']);
    
};
cs


ㄷ. 실행결과 : styles.min.css 로 압축되어있다.






   ATOM 에 Grunt 패키지 설치하고 플러그인 모두 한번에 실행해보기


ATOM 에서 grunt-runner package 를 설치한다.




Gruntfile.js 에 여태까지의 플러그인의 내용을 한번에 작성한다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
module.exports = function(grunt) {
 
    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
 
        /*******************************************************************************************************************************
        *
        *    1. jshint 로 유효성검사
        *
        *******************************************************************************************************************************/
        jshint:{
            //all: ['Gruntfile.js', 'js/test_01.js', 'js/test_02.js'] // 기본적으로 자기자신을 포함하고, 직접 지정해서 사용
            //all: ['js/*'] // 혹은 js 폴더의 모든 파일을 검사
            //all: ['js/etc/*.js'] //측정폴더의 모든 js 검사
            all: ['js/test_1.js''js/test_2.js'],
            options:{
                force: true// true로 설정시 error 가 있다하더라도 fail 시키지않고 계속 진단
                reporter: require('jshint-stylish')
            }
        },
 
        /*******************************************************************************************************************************
        *
        *    2. concat 으로 파일 통합
        *
        *******************************************************************************************************************************/
        concat:{
            options: {
                stripBanners:  true,
                //separator: ';',
                separator: '',
                banner: '/* <%= pkg.name %> - v<%= pkg.version %> - '+'<%= grunt.template.today("yyyy-mm-dd") %> */',  //동작 시점의 날짜가 출력
                footer : "",
            },
 
            basic:{
                src:['js/test_1.js','js/test_2.js'],
                dest:'build/built.js'
            },
 
            extras:{
                src:['css/test_1.css','css/test_2.css'],
                dest:'build/styles.css'
            },
 
            // Invalid or Missing Files Warning 잘못 또는 누락된 파일 경고 : 해당파일이 없거나 유효하지 않으면 경고
            missing:{
                src:['log/grunt_compiled'],
                dest: 'log/grunt_compiled/compiled_js.log',
                nonull: true
            }
        },
 
        /*******************************************************************************************************************************
        *
        *    3. ugilfy 로 js 압축
        *
        *******************************************************************************************************************************/
        uglify:{
            options: {
                mangle: false//변수와 함수 이름을 변경되는 것을 방지할경우 false 사용
                compress: {
                    drop_console: true //콘솔경고해제
                },
                //beautify: true // 디버깅이나 문제해결을 위해 사용
            },
            build: {
                src: 'build/built.js',
                dest: 'build/built.min.js'
            }
        },
 
        /*******************************************************************************************************************************
        *
        *    4. cssmin 으로 css 압축
        *
        *******************************************************************************************************************************/
        cssmin:{
            minify:{
                expand: true,
                cwd: "build/"// css 폴더 위치
                src:['*.css''!*.min.css'], // 파일지정, 이때 .min.css 는 제외한다.
                dest:'build'// 출력폴더 지정
                ext:".min.css" // 확장자 지정
            },
            options:{
                keppSpecialComments: 0 //  default : '!' 가 붙은 주석 보존, 1 : '!' 가 붙은 주석 중 첫번째 주석만 보존, 0 : 모든 주석 제거
            }
        }
 
 
    });
 
    //Gruntfile 내에서 자바스크립트의 코드로 아래의 명령을 사용
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-cssmin');
 
    //grunt 명령어로 실행할 작업
    grunt.registerTask('default', ['jshint''concat''uglify''cssmin']);
 
};
 
cs




package > Grunt Runner > Toggle Panel 실행하여 활성화시킨다.



Start 클릭하고 default 입력후 엔터



아래와 같이 Grunt 가 실행되고 build 에 여태까지 작업했던 내용들이 한번에 생성된다.






   최종 화면비교


좌측이 Grunt 전에 우리가 실행했던 before.html, 우측이 Grunt 를 모두 실행하고 나서 결과물인 after.html



댓글