Vue 프로젝트를 통해서 Webpack을 알아보자.(vue simple webpack project)

들어가기

이번에 Vue.js를 공부하게 되면서 Webpack이라는 것을 실제 접하게 되었다. 물론 인터넷에서 Webpack이라는 말은 자주 들어보았지만, 이것에 대해 전혀 감이 없었다. 이번 기회에 Webpack에 대한 아주 간단한 개념정리와, webpack 번들링을 한번 해보겠다. Vue simple-webpack 프로젝트를 사용한다.

참고로 본인은 Vue도 Webpack도 잘 모른다. 그냥 지금까지 공부한 것을 아주 후려처서 정리한 내용이다.


Webpack의 정의

웹팩은 모듈번들러다. 난 처음 이말을 들었을때, 이게 대체 무슨소린가 했다. 프론트엔드 기술에 대한 막연한 두려움이 아마 이때 생겨 났던것 같다.

일단 웹팩이 무엇인지 알기위해 가장 쉬운 방법은 실질적으로 개발자가 웹팩으로 무엇을 하는지 알면 된다. 일단 다음 이미지를 확인해 보자.

내 Spring 샘플 프로젝트의 html의 일부분이다.

위 html파일을 보면 상당히 많은 js 파일을 추가적으로 가져오는 것을 알 수 있다. 요즘 웹 화면은 PC, 모바일의 앱처럼 다양한 기능과 유려한 화면구성을 갖는다.

당연히 html 페이지는 수많은 js, css, image 등을 추가적으로 가져와야 한다.

웹팩은 이 추가적으로 가져와야 할 이 수많은 것들을(js, css, image) 하나의 js파일로 만들어 버린다.

즉 html 파일은 이렇게 간단하게 변한다는 의미이다.

수많은 외부 리소스등을 하나의 js파일로 묶어서 사용함으로써, 기존에 발생한 수많은 network request가 하나의 request로 만들어 브라우저의 로딩성능을 높일 수 있다. (번들링 뿐만 아니라 더불어 난독화등 다양한 기능을 추가적으로 제공한다.)

그리고 번들링(하나로 합칠때)할때 JS 모듈의 의존관계를 알아서 반영해준다. 내부적으로 대체 어떻게 돌아가는지는 몰라도 참으로 신박한 녀석이다. Webpack과 비슷한 모듈번들러로 gulp, grunt라는 것도 있다고 한다.

하지만 현재 기능, 성능면에서 Webpack이 가장 뛰어 나다고 한다.


Vue 프로젝트를 이용한 Webpack의 간단 실습 및 설명

실제 Vue의 웹팩 프로젝트를 통해 실습과 설명을 진행하겠다. 잘 모를땐 일단 키보드를 때려보는게 좋을거 같다.

전재조건 :Node와 Vue CLI가 설치되어 있어야 한다.

1.특정 TestVueSample 이라는 폴더를 만들고 Vue webpack-simple 프로젝트를 만들자.

볼더를 만들고 그 경로에서 아래 명령어로 Vue webpack simple 프로젝트를 만들자.

1
vue init webpack-simple

vue webpack simple 프로젝트를 생성하자.

명령어로 생성된 파일과 폴더중 중요한 것들을 집어보자.


가.package.json

위 파일은 npm 패키지 정보를 담고 있다.

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
{
"name": "testvuesample",
"description": "webpack test",
"version": "1.0.0",
"author": "hanumoka",
"license": "MIT",
"private": true,
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
},
"dependencies": {
"vue": "^2.5.11"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
],
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.0",
"babel-preset-stage-3": "^6.24.1",
"cross-env": "^5.0.5",
"css-loader": "^0.28.7",
"file-loader": "^1.1.4",
"vue-loader": "^13.0.5",
"vue-template-compiler": "^2.4.4",
"webpack": "^3.6.0",
"webpack-dev-server": "^2.9.1"
}
}

scripts 항목을 보면 dev, build가 있다. npm run dev 명령어를 실행하면 cross-env NODE_ENV=development webpack-dev-server --open --hot 명령어가 실행된다. 마찬가지로 npm run build 명령어를 실행하면 cross-env NODE_ENV=production webpack --progress --hide-modules 가 실행된다.

npm run build에 맵핑된 명렁어를 보면 webpack 명렁어가 들어있다. 즉 npm run bulid 명령어를 실행하면 방금 생성한 Vue simple webpack 프로젝트를 webpack으로 빌드하게 된다.


나.index.html

방금 생성한 뷰 프로젝트의 진입점 html이다. /dist/build.js 를 참고 하고 있는데, 앞서 말했듯이 이것은 Webpack에 의해 번들링된 결과물이다.

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>testvuesample</title>
</head>
<body>
<div id="app"></div>
<script src="/dist/build.js"></script>
</body>
</html>


다.webpack.config.js

위 파일은 webpack이 프로젝트를 빌드할때 참고하는 설정 파일이다. webpack의 핵심파일이라고 생각하면 된다. 이 파일에는 webpack core인 entry, output, loaders, plugins 의 정보가 들어간다.

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

var path = require('path')
var webpack = require('webpack')

module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
}, {
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
}
// other vue-loader options go here
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['*', '.js', '.vue', '.json']
},
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true
},
performance: {
hints: false
},
devtool: '#eval-source-map'
}

//이 부분은 배포할때 동작하는 로직으로 souceMap을 생성한다.
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
])
}

아 길다... 어렵다... 모르겠다.

중요한 것만 보자.

1
2
3
4
5
6
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'), //프로넥트 내부의 dist 폴더 경로에 빌드 결과물 생성
publicPath: '/dist/', //index.html 파일기준 참조 폴더(말이 좀 이상한데,뒤에 설명...)
filename: 'build.js' //Webpack에 의해서 만들어진 최종 파일
}

entry와 output이다. entry는 말 그대로 Webpack이 번들링할때 사용하는 진입점 js 파일이다. output은 Webpack이 번들링한 그 결과물에 대한 설정 정보이다.

그리고 module 영역도 살펴보자.

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
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
}, {
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
}
// other vue-loader options go here
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},

모듈 내부에 있는 것들은 loader 이다. WebPack은 css, js, image 등을 하나로 뭉쳐서 하나의 파일로 번들링(build.js) 한다고 했다. loader는 이름 그대로 WebPack이라는 압축기에 Css 등을 수집하여 적재해주는 트럭 같은 녀석이다.

1
2
3
4
5
6
7
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
}

위 녀셕을 보면 프로젝트의 모든 css 확장자 파일들을 vue-style-loader와 css-loader라는 로더를 사용해서 WebPack에게 적재 시키겠다는 의미이다.

여기에서 Vue를 위한 Vue loader도 있다.

1
2
3
4
5
6
7
8
9
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
}
// other vue-loader options go here
}
}

마찬가지로 vue 확장자를 갖는 파일들을 vue-loader로 적재한다. 이 부분을 조금더 설명하자면, 브라우저는 vue확장자 파일을 인식을 하지 못한다. 개발할때 만들어진 Vue 파일들은 WebPack에 적재하고, WebPack은 이 Vue파일들을 html파일로 변환하여, 브라우저가 인식 할수 있게 컨버팅 해준다.

위 설정에는 없지만 webpack에는 plugins 이라는 것도 있다. 사실 이부분은 잘 모른다. 대충 찾아보니 webpack에 의해 번들된 결과물에 여러가지 후처리를 할수 있는 유틸리티 정도의 역할을 하는 것 같다.

예를 들어 번들링된 js 소스를 난독화, css를 sass로 변환 등 다양한 기능이 있는 것 같다.

2.일단 Vue Webpack simple 프로젝트를 동작 시켜보자.

방금 예제에서 프로젝트 생성까지만 했다. 최초 생성시 npm install 명령어로 모듈들을 다운 받아야 한다.

아래 명령어를 이용해서 라이브러리를 설치하자.

1
npm install

npm install 명령어으로 라이브러리 다운로드

그리고 npm run dev 명령어를 입력해보자.

앞서 설정에서 봤듯이 cross-env NODE_ENV=development webpack-dev-server --open --hot 명령어를 직접 입력해도 된다.

자동으로 웹 브라우저창이 뜨며 Vue 프로젝트가 실행된다.

이 것은 webpack-dev-server가 동작하면서 메모리에 실시간으로 프로젝트를 웹펙으로 빌드하고 있는 상황이다. 따라서 프로그램을 수정하면 실시간으로 브라우저에 반영된다.

3.Vue webpack-simple 프로젝트를 webpack으로 빌드해보자.

이번에는 npm run build 명령어를 실행해 보자.

dist폴더와 그 내부에 webpack의 빌드 결과물이 생성된다.

그렇다면 webpack-dev-server없이 index.html 파일을 브라우저에 열면 vue 프로젝트가 동작 할까?

이상하게 동작이 되지 않는다.

ㅋㅋㅋ 안된다.

이유는 지금 webpack.config.js 의 output 설정이 좀 이상하기 때문이다.

생성된 dist 폴더를 C 드라이브로 옮겨보자.

dist 폴더를 복사해서 C드라이브에 옮겨보면 잘 동작한다.

음 그렇다면 설정을 변경해서, index.html 파일의 현재경로의 dist 폴더를 사용하게 수정해보자.

index.html 파일에 build.js 경로앞에 점을 찍어주자.

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>testvuesample</title>
</head>
<body>
<div id="app"></div>
<script src="./dist/build.js"></script> <!-- 맨앞에 점을 찍자. -->
</body>
</html>

webpack.config.js 파일에 output 영역도 수정해주자. publicPath에도 맨 앞에 점을 찍어주자.

1
2
3
4
5
output: {
path: path.resolve(__dirname, './dist'),
publicPath: './dist/', // 여기도 경로 맨앞에 점을 찍자
filename: 'build.js'
},

다시 npm run build 를 실행하고, index.html 파일을 브라우저에서 실행해 보자.

정상동작을 확인 할 수 있다.

이것으로 Vue webpack-simple 프로젝트를 webpack으로 빌드해 보았다.

잠깐 빌드 결과물을 살펴보자.

dist 폴더 내부

build.js, build.js.map, logo.png 3개의 파일이 있다.

wepback이라는 모듈 번들러가 Vue simple-project를 build.js라는 파일 하나로 꽉꽉 뭉쳐하나의 파일로 만들었다. 덕분에 index.html에 복잡한 js, css, image 등 리소스를 가져오는 소스가 사라졌다.

build.js.map 는 사실 정확히 모르겠지만, source map이라고 해서 webpack이 프로젝트를 빌드할때 그 과정에 대한 설명서 같은 것으로 보여진다. 이 파일은 디버깅할때 사용된다고 한다.

그리고 logo.png는 왜..... 이것도 build.js 내부로 들어가는게 아닌가???? 아 잘 모르겠다.


마무리

사실 Vue, Webpack 둘다 모르는 상황에서 이것저것 공부해보려니 막히는 부분이 많다. 차근차근 공부해 나가야 겠다.


Related Posts

http://blog.jeonghwan.net/js/2017/05/15/webpack.html

http://jusungpark.tistory.com/52

https://webpack.js.org/concepts/#entry