Webpack-v2 Config Usage

webpack2 사용 예제

실제로 webpack2 어떻게 작성하고 사용하는지 샘플 코드로 작성 후 한번 살펴 보자.

디렉토리 구성 샘플

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[src]
[css]
-style.css
[img]
[js]
-module-a.js
-module-b.js
-module-c.js
[scss]
-style.scss
-entry-index.js
-index.html

-package.json
-webpack.config.js

파일 구성 샘플

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- index.html -->

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<h1>나는 문서의 제목이얌! 내가 짱이지!</h1>
<p>IE11+에서 나는 드래그 안 될 걸?!</p>

<script src="./bundle.js"></script>
</body>
</html>
1
2
3
4
// module-a.js

const a = '나는 a';
export const ab = a + ', a를 외부에 노출시키지 않고 변수 a를 활용!';
1
2
3
// module-b.js

export const a = '모듈 a에 존재하는 변수 a와는 다른 스코프를 가짐';
1
2
3
// module-c.js

export const b = '나도 써주랑!';
1
2
3
4
5
6
7
8
9
10
11
// entry-index.js

import '../css/style.css';
import '../scss/style.scss';

import {ab} from './module-a';
import {a} from './module-b';
import {b} from './module-c';

console.log(ab); // "나는 a, a를 외부에 노출시키지 않고 변수 a를 활용!"
console.log(a); // "모듈 a에 존재하는 변수 a와는 다른 스코프를 가짐"
1
2
3
4
5
/* style.css */

p {
user-select: none
}
1
2
3
4
5
6
/* style.scss */

$color: red;
h1 {
color: $color
}
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
// webpack.config.js

const webpack = require('webpack');
const autoprefixer = require('autoprefixer');

module.exports = {
devtool: 'source-map',
entry: './src/entry-index.js',
output: {
filename: 'bundle.js',
},
// 플러그인 옵션
plugins: [
new webpack.optimize.UglifyJsPlugin({
compressor: {
warnings: false,
}
}),
new HtmlWebpackPlugin({
title: 'Project Demo',
minify: {
collapseWhitespace: true
},
hash: true,
template: './src/index.html'
})
],
// 파일들에 영향을 주는 옵션
module: {
rules: [{
test: /\.js$/,
// exclude: /(node_modules|bower_components)/,
use: [
{loader: 'babel-loader', options: {
presets: [
// ['es2015', {moduels: false}]
['latest', {moduels: false}]
]
}}
]
}, {
test: /\.css$/,
// exclude: /node_modules/,
use: [
'style-loader',
{loader: 'css-loader', options: {sourceMap: true}},
{loader: 'postcss-loader', options: {
plugins: (loader) => [
autoprefixer({
browsers: ['last 2 version', 'ie >= 10']
})
]
}}
]
}, {
test: /\.(scss|sass)$/,
// exclude: /node_modules/,
use: [
'style-loader',
{loader: 'css-loader', options: {sourceMap: true}},
{loader: 'postcss-loader', options: {
plugins: (loader) => [
autoprefixer({
browsers: ['last 2 version', 'ie >= 10']
})
]
}},
{loader: 'sass-loader', options: {sourceMap: true}}
]
}]
}
};

그럼 실제로 번들링을 해보자.

1
$ webpack -w

위 명령어를 실행하면 모듈들이 번들링되며 엔트리 포인트와 엔트리 포인트에 관련된 모듈들이 변경될 때마다 다시 번들링되는 감시(watch)를 진행하게 된다.
Ctrl + C 키를 누르면 빠져나올 수 있다.

그리고나서 다시 디렉토리를 보면 다음과 같은 파일이 생긴 것을 볼 수 있다.

  1. bundle.js
  2. bundle.js.map

웹팩 설정 파일 Development(개발모드) / Production(배포모드) 구분

webpack의 개발 및 배포용 환경은 보통 구분되어져야 하는데 이에 따라 기본환경파일인 webpack.config.js 는 보통 webpack.donfig.dev.js(개발용) 및 webpack.config.prod.js(배포용) 으로 구분한다.
개발모드에서는 source-map 등 debugging용 설정등이 추가되고, 배포모드에서는 소스크기등 최적화용 설정등이 추가된다.

그럼 개발용 파일과 배포용 파일을 분리해 보자!
우선 디렉토리를 아래와 같이 바꾼다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[src]
[css]
-style.css
[img]
[js]
-module-a.js
-module-b.js
-module-c.js
[scss]
-style.scss
-entry-index.js
-index.html

package.json
-webpack.config.dev.js
-webpack.config.prod.js

몇몇 파일들도 아래와 같이 변경한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- index.html -->

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<h1>나는 문서의 제목이얌! 내가 짱이지!</h1>
<p>IE11+에서 나는 드래그 안 될 걸?!</p>

<span></span>
<button id="btn" class="btn btn-warning"><i class="fa fa-address-book" aria-hidden="true"></i></button>
<img src="./img/logo_webpack.png" alt="로고">
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// entry-index.js

if (process.env.NODE_ENV !== 'production') {
require('../index.html')
}

import 'bootstrap/dist/css/bootstrap.min.css';
import 'font-awesome/css/font-awesome.min.css';
import $ from 'jquery/dist/jquery.slim';

import './css/style.css';
import './scss/style.scss';

import { ab } from './js/module-a';
import { a } from './js/module-b';
import { b } from './js/module-c';

console.log(ab); // "나는 a, a를 외부에 노출시키지 않고 변수 a를 활용!"
console.log(a); // "모듈 a에 존재하는 변수 a와는 다른 스코프를 가짐"
console.log(b);

$('#btn').on('click', function() {
alert('test');
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* style.scss */

$color: blue;
$square: 90px;

h1 {
box-sizing: border-box;
color: $color
}
span {
display: inline-block;
background-image: url('../img/logo_webpack.png');
width: $square;
height: $square;
}

추가로 패키지를 설치할 필요가 있다.(설치되어 있거나 필요없는 패키지는 제외하면 된다.)

1
2
3
4
$ npm i -g webpack-dev-server
$ npm i -D webpack-dev-server raw-loader webpack-browser-plugin extract-text-webpack-plugin webpack-strip clean-webpack-plugin
$ npm i -S jquery bootstrap font-awesome
$ npm i -D url-loader file-loader
  1. webpack-dev-server: -g로 설치하는 이유는 해당 명령어를 터미널에서 쓰기 위함이고 다시 한 번 -D로 설치하는 이유는 현재 프로젝트에서 해당 패키지를 쓰기 위함이다. webpack-dev-server는 실제 눈에 보이지 않는 디렉토리를 만들고 그 디렉토리에 번들링을 진행하고 watch하며 테스트를 하는 웹팩 개발용 서버이다.
  2. raw-loader: html 파일을 핫리로드하게 만드는 로더.
  3. webpack-browser-plugin: webpack-dev-server에서 번들링을 끝낸 후 자동으로 브라우저를 열어주는 플러그인. 자세한 옵션은 webpack-browser-plugin을 확인하자.
  4. extract-text-webpack-plugin: 스타일 시트를 따로 빼기 위한 플러그인
  5. webpack-strip: js 파일에서 디버깅을 위해 찍어본 로그를 삭제
  6. clean-webpack-plugin: 배포용 파일을 빌드하기 전에 배포용 디렉토리를 지워주는 플러그인
  7. jquery bootstrap font-awesome: 라이브러리 모듈 로더 설치
  8. url-loader file-loader: jquery, bootstrap, font-awesome 이미지 모듈 사용을 위한 로더

Development(개발모드)

webpack.config.dev.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
// webpack.config.dev.js

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const autoprefixer = require('autoprefixer');
const WebpackBrowserPlugin = require('webpack-browser-plugin');

module.exports = {
devtool: 'cheap-eval-source-map',
entry: [
'./src/entry-index.js'
],
output: {
filename: 'bundle.js',
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
//title: 'Project Demo',
template: './src/index.html'
//filename: './index.html'
}),
new WebpackBrowserPlugin()
],
module: {
rules: [{
test: /\.js$/,
use: [
{loader: 'babel-loader', options: {
presets: [
['latest', {moduels: false}]
]
}}
]
}, {
test: /\.css$/,
use: [
'style-loader',
{loader: 'css-loader', options: {sourceMap: true}},
{loader: 'postcss-loader', options: {
plugins: (loader) => [
autoprefixer({
browsers: ['last 2 version', 'ie >= 10']
})
]
}}
]
}, {
test: /\.(scss|sass)$/,
exclude: /node_modules/,
use: [
'style-loader',
{loader: 'css-loader', options: {sourceMap: true}},
{loader: 'postcss-loader', options: {
plugins: (loader) => [
autoprefixer({
browsers: ['last 2 version', 'ie >= 10']
})
]
}},
{loader: 'sass-loader', options: {sourceMap: true}}
]
}, {
test: /\.html$/,
use: [
'raw-loader'
]
}, {
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: [
{loader: 'url-loader', options: {
limit: 10000,
mimetype: 'application/font-woff',
name: 'fonts/[name].[ext]'
}}
]
}, {
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: [
{loader: 'file-loader', options: {
name: 'fonts/[name].[ext]'
}}
]
}, {
test: /\.(jp(e)g|gif|png)?$/,
use: [
{loader: 'file-loader', options: {
name: 'img/[name].[ext]'
}}
]
}]
},
devServer: {
contentBase: path.resolve(__dirname, 'src'),
host: '127.0.0.1',
port: 4000,
hot: true
}
};

Production(배포모드)

배포용 설정 파일인 webpack.config.prod.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
106
107
108
109
110
111
112
// webpack.config.prod.js

const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const autoprefixer = require('autoprefixer');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
entry: [
'./src/entry-index.js'
],
output: {
path: path.join(__dirname, 'build'),
filename: 'js/[name].bundle.js'
},
plugins: [
new CleanWebpackPlugin(['build']),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
new webpack.optimize.UglifyJsPlugin({
compressor: {
warnings: false,
}
}),
new webpack.optimize.OccurrenceOrderPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html',
minify: {
collapseWhitespace: true,
keepClosingSlash: true,
removeComments: true,
},
xhtml: true
}),
new ExtractTextPlugin({
filename: './css/bundle.min.css',
disable: false,
allChunks: true,
})
],
module: {
rules: [{
test: /\.js$/,
use: [
{loader: 'babel-loader', options: {
presets: [
['latest', {moduels: false}]
]
}}
]
}, {
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{loader: 'css-loader', options: {minimize: true}},
{loader: 'postcss-loader', options: {
plugins: (loader) => [
autoprefixer({
browsers: ['last 2 version', 'ie >= 10']
})
]
}}
],
publicPath: '../'
})
}, {
test: /\.(scss|sass)$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{loader: 'css-loader', options: {minimize: true/*, url: false*/}},
{loader: 'sass-loader', options: {outputStyle: 'compact'}},
{loader: 'postcss-loader', options: {
plugins: (loader) => [
autoprefixer({
browsers: ['last 2 version', 'ie >= 10']
})
]
}}
],
publicPath: '../' // background-url 경로 prefix 값으로 들어간다.
})
}, {
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: [
{loader: 'url-loader', options: {
limit: 10000,
mimetype: 'application/font-woff',
name: 'fonts/[name].[ext]'
}}
]
}, {
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: [
{loader: 'file-loader', options: {
name: 'fonts/[name].[ext]'
}}
]
}, {
test: /\.(jp(e)g|gif|png)?$/,
use: [
{loader: 'file-loader', options: {
name: 'img/[name].[ext]'
}}
]
}]
}
};

웹팩의 설정 파일의 기본적인 이름은 webpack.config.js이다.
그래서 webpack 이라는 명령어만 붙여도 자동으로 webpack.config.js 파일을 인식했는데,
우리는 임의로 설정 파일의 이름을 바꿨기 때문에 달리 진행해야한다.

개발을 진행하기 위해서는 터미널에 아래와 같이 입력을 해야한다.

1
$ webpack-dev-server -d --config webpack.config.dev.js

배포를 진행하기 위해서는 아래와 같이 입력을 해야한다.

1
$ webpack --config webpack.config.prod.js

package.json 의 script 에 개발/배포 script 지정

하지만 위와 같은 작업은 번들링 할때마다 매우 번거롭게 느낄수 있다. npm의 스크립트를 이용하면 좀 더 간단하게 명령어로 번들링 할 수 있다.
우선 위의 개발/배포 명령어를 package.json 의 scripts 부분에 아래와 같이 추가해준다.

1
2
3
4
5
"scripts": {
"dev": "webpack-dev-server -d --config webpack.config.dev.js",
"build": "webpack --config webpack.config.prod.js",
"test": "echo \"Error: no test specified\" && exit 1"
}

이제는 개발을 진행하고자 할 때는 아래와 같이 입력해주면 된다.

1
$ npm run dev

배포를 진행하고자 할 때는 아래과 같이 입력해주면 된다.

1
$ npm run build

테스트 샘플로 진행한 전체 package.json 파일은 다음과 같다.

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
{
"name": "webpack-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server -d --config webpack.config.dev.js",
"build": "webpack --config webpack.config.prod.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"webpack"
],
"author": "woonyzzang",
"license": "MIT",
"devDependencies": {
"autoprefixer": "^7.1.0",
"babel-core": "^6.24.1",
"babel-loader": "^7.0.0",
"babel-preset-latest": "^6.24.1",
"clean-webpack-plugin": "^0.1.16",
"css-loader": "^0.28.1",
"extract-text-webpack-plugin": "^2.1.0",
"file-loader": "^0.11.1",
"html-webpack-plugin": "^2.28.0",
"node-sass": "^4.5.3",
"postcss-loader": "^2.0.5",
"raw-loader": "^0.5.1",
"sass-loader": "^6.0.5",
"style-loader": "^0.17.0",
"url-loader": "^0.5.8",
"webpack": "^2.5.1",
"webpack-browser-plugin": "^1.0.20",
"webpack-dev-server": "^2.4.5",
"webpack-strip": "^0.1.0"
},
"dependencies": {
"bootstrap": "^3.3.7",
"font-awesome": "^4.7.0",
"jquery": "^3.2.1"
}
}

참조

공유하기