참고자료 :
https://www.youtube.com/watch?v=cp_MeXO2fLg&list=PLuHgQVnccGMChcT9IKopFDoAIoTA-03DA ,
https://webpack.js.org/
이전에 bundler를 왜 사용해야 하는지 살펴보았습니다.
이번 글은 bundler 중 대표적으로 사용되고 있는 webpack의 설치부터 실행을 위한 기본 설정에 대해 쓴 글입니다.
웹팩(webpack)은 npm을 이용하여 설치해야 합니다. npm에 대해 모르시는 분은 찾아보시기 바랍니다.
먼저 프로젝트를 진행할 디렉토리를 만듭니다. 그리고 해당 폴더에서 npm init -y 명령어를 입력해 npm을 초기화 시켜줍니다. 그러면 해당 폴더에 package.json 파일이 생기게 됩니다. 그 후 npm i -D webpack webpack-cli 명령어를 입력하여 웹팩과 웹팩 CLI 패키지를 설치합니다.
$ mkdir webpack-config
$ cd webpack-config
$ npm init -y
$ npm i -D webpack webpack-cli
그러면 Package.json 파일에 다음과 같이 나오면 웹팩이 올바르게 설치된 것입니다.
{ ...
"devDependencies": {
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
...
}
그러면 이제 웹팩의 기본 설정에 대해 하나씩 살펴보겠습니다.
기본적으로 webpack은 환경설정 파일을 사용할 필요없이 다음과 같이 cli를 이용하여 간단하게 build 할 수 있습니다.
$ webpack --entry [entry 파일 이름] --output [output 파일 이름]
하지만 일반적으로 프로젝트에서 webpack의 구조는 간단하지 않고, 많은 기능들을 추가적으로 다루어야 합니다. 따라서 환경설정 파일을 통해 build 해주어야 합니다.
이를 위해 다음과 같은 webpack.config.js 파일을 루트 디렉토리에 만들어 줍니다.
webpack.config.js
module.exports = {}
이를 실행 시키려면 다음과 같이 입력해주면 됩니다.
$ webpack
만약 webpack.config.js가 아닌 다른 이름으로 만들 경우 이를 실행시키기 위해선 다음과 같이 입력해주어야 합니다.
$ webpack --config [설정 파일 이름]
웹팩 환경 설정에 대해 알아보도록 하겠습니다.
mode 매개 변수를 development, production 또는 none으로 설정하면 각 환경에 해당하는 webpack의 내장 최적화를 사용할 수 있습니다. 아무런 설정을 하지 않으면 웹팩은 production으로 자동 설정합니다. webpack.config.js에 다음과 같이 설정해주면 됩니다.
webpack.config.js
module.exports = {
mode: 'production' // or "development" or "none"
};
Entry point는 내부 종속성 그래프 작성을 시작하기 위해 번들링 프로세스를 시작할 지점을 나타냅니다. webpack은 Entry point에 의존하는 다른 모듈과 라이브러리를 파악합니다. Entry point는 한 개일 수도 있고, 여러 개일 수도 있습니다.
webpack.config.js에 다음과 같이 설정해주면 됩니다.
webpack.config.js
한 개일 때
module.exports = {
entry: './source/index.js'
}
여러 개일 때
module.exports = {
entry:{
index : "./source/index.js",
about :"./source/about.js",
},
};
output 설정은 웹팩이 컴파일 된 파일을 어떻게 디스크에 생성할지 표현하는 것입니다. entry point는 여러개 있을 수 있지만, output은 오직 하나만 지정할 수 있습니다.
webpack.config.js에 다음과 같이 설정해주면 됩니다.
webpack.config.js
module.exports = {
output: {
filename: 'bundle.js',
}
};
이렇게 설정해주면 dist 디렉토리에 bundle.js 파일이 생성됩니다. 파일이 생성되는 폴더의 위치를 변경하고 싶다면 다음과 같이 설정을 추가하면 됩니다.
webpack.config.js
const path = require('path');
module.exports = {
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'public'),
}
};
지금의 경우 path 모듈을 사용하여 path를 지정해주었습니다. __dirname는 현재 파일이 위치한 경로를 의미합니다. 그러므로 path.resolve(__dirname, 'public') 는 현재 파일 경로에 위치한 public 폴더를 의미합니다.
결론적으로, 위와 같이 설정을 해주면 public 폴더에 bundle.js 파일이 생성됩니다.
만약 여러 개의 entry point를 가지고 있다면 다음과 같이 설정합니다.
webpack.config.js
module.exports = {
entry:{
index : "./source/index.js",
about :"./source/about.js",
},
output: {
filename: '[name]_bundle.js',
path: path.resolve(__dirname, 'public'),
}
};
다음과 같이 [name]_bundle.js 라고 설정해주면 해당 entry의 name을 받아 bundle 파일을 생성합니다. 위의 경우 index_bundle.js, about_bundle.js라는 파일이 public 폴더 안에 생성됩니다.
이제 파일을 만들어 webpack을 실행시켜 보겠습니다. 아래와 같이 파일을 만듭니다.
webpack-config/source/hello.js
var word = "Hello";
export default word;
webpack-config/source/world.js
var word = "World";
export default word;
webpack-config/source/index.js
import hello_word from './hello.js';
import world_word from './world.js';
document.querySelector("#root").innerHTML = hello_word + " " + world_word;
webpack-config/source/about.js
import hello_word from './hello.js';
import world_word from './world.js';
document.querySelector("#root").innerHTML = world_word + " " + hello_word;
이제 위에서 webpack.config.js에 설정한대로 webpack 프로세스를 실행하면 public 폴더에 index_bundle.js 파일과 about_bundle.js 파일이 생기는 것을 확인할 수 있습니다.
이제 아래와 같이 html 파일을 만들어 번들링 된 결과가 제대로 나오는지 확인해보겠습니다.
webpack-config/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Index</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
</head>
<body>
<h1>Hello, Webpack</h1>
<div id="root"></div>
<script src="./public/index_bundle.js"></script>
<a href="./about.html">about</a>
</body>
</html>
webpack-config/about.html
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>About </title>
</head>
<body>
<h1>Hello, About</h1>
<div id="root"></div>
<script src="./public/about_bundle.js"></script>
<a href="./index.html">index</a>
</body>
</html>
실행 결과
index.html
about.html
이와 같이 index.js와 about.js에 종속된 hello.js와 world.js가 제대로 번들링된 것을 확인할 수 있습니다.
위와 같은 과정을 거치면 다음과 같은 파일 구조를 가지게 됩니다.
webpack-config
│ index.html
│ about.html
│ package-lock.json
│ package.json
│ webpack.config.js
│
├─node_modules
└─ ...생략
│
├─public
│ about_bundle.js
│ index_bundle.js
│
└─source
about.js
hello.js
index.js
world.js
Loader는 모듈의 소스 코드에 적용되는 변환입니다. 파일을 import하거나 load할 때 파일을 사전 처리 할 수 있습니다. Loader는 파일을 다른 언어로 변환시킵니다. 예를 들어 TypeScript에서 JavaScript로 변환하거나 인라인 이미지를 데이터 URL로 load 할 수 있습니다. 또한, Loader를 사용하면 JavaScript 모듈에서 바로 CSS 파일을 import 하는 등의 작업을 수행 할 수 있습니다.
여기선 Loader을 통해 Javascript 모듈에서 css를 import하여 같이 번들링하는 작업을 진행해보겠습니다.
우선 css-loader과 style-loader을 설치해주어야 합니다.
$ npm i -D css-loader style-loader
css-loader는 css 파일들을 읽어주고, style-loader는 읽은 css 파일들을 style 태그로 만들어 head 태그 안에 넣어주는 기능을 수행합니다.
그 후 webpack.config.js를 다음과 같이 설정합니다.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
`style-loader`,
`css-loader`,
]
}
],
}
};
test 는 loader를 적용할 파일을 지정해주는 것입니다. 정규표현식을 이용하여 확장자가 .css인 파일을 지정합니다.
use는 사용할 loader를 설정해 주는 것입니다. loader는 아래에서부터 적용되므로 css-loader, style-loader 순으로 적용됩니다.
이제 css 파일을 만들어 적용해보겠습니다.
webpack-config/style/index.css
body {
color: white;
background-color: black;
}
webpack-config/source/index.js
import hello_word from './hello.js';
import world_word from './world.js';
import '../style/index.css';
document.querySelector("#root").innerHTML = hello_word + " " + world_word;
위와 같이 css 파일을 index.js에서 import합니다. 그 후
$ webpack
명령어로 index.js를 build하게 되면 public 폴더에 index_bundle.js 파일이 생성됩니다. 이를 script를 통해 불러오면 다음과 같은 결과가 나오게 됩니다.
실행 결과
이처럼 loader를 이용하여 css 파일을 불러오지 않아도 css가 적용할 수 있습니다.
Plugin은 웹팩의 기본적인 동작에 추가적인 기능을 제공하게 해줍니다. 이는 Loader가 할 수 없는 일들을 수행할 수 있습니다.
Loader는 파일을 해석하고 변환하는 과정에 관여하여 모듈을 처리합니다. 반면에, Plugin은 번들링된 파일을 처리합니다. 다시 말해, Loader는 모듈을 최종적인 output으로 변환하는 과정에 관여하는 것이고, Plugin은 그렇게 생성된 output을 변환하는 것입니다.
Plugin은 다양한 커스텀 기능을 제공합니다. 번들된 파일을 난독화, 압축할 수도 있고, 파일복사, 파일추출, 별칭사용 등과 같은 작업을 수행할 수도 있습니다.
Plugin을 사용하려면 require()하고 플러그인 배열에 추가해야합니다. 대부분의 플러그인은 옵션을 통해 사용자 정의 할 수 있습니다. 플러그인을 여러 번 사용할 수 있으므로 new 연산자를 사용하여 플러그인을 호출하여 인스턴스를 작성해야합니다.
수많은 플러그인이 있지만, 이 글에선 html-webpack-plugin을 예제로 사용하겠습니다. html-webpack-plugin은 HTML 파일을 template로 지정하면 그것에 웹팩 빌드한 output 결과를 적용합니다.
우선 html-webpack-plugin을 설치합니다.
npm i -D html-webpack-plugin
그 후 webpack.config.js를 다음과 같이 설정합니다.
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: {
index: './source/index.js',
about: './source/about.js',
},
output: {
path: path.resolve(__dirname, 'public'),
filename: '[name]_bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
filename: 'indexResult.html',
chunks:['index'],
}),
new HtmlWebpackPlugin({
template: './about.html',
filename: 'aboutResult.html',
chunks:['about'],
}),
]
};
template는 기준이 되는 html 파일입니다.
filename은 결과적으로 생성되는 파일의 이름을 의미합니다.
chunks는 entry point를 의미합니다. 'index'로 주면 ./source/index.js가 번들링된 결과가 HTML 파일에 추가됩니다.
위와 같이 설정하고 build를 하게 되면 다음과 같이 public 폴더 안에 다음과 같은 파일이 생성됩니다.
webpack-config/public/indexResult.html
...
<body>
<h1>Hello, Webpack</h1>
<div id="root"></div>
<script src="./public/index_bundle.js"></script>
<a href="./about.html">about</a>
<script src="index_bundle.js"></script>
</body>
webpack-config/public/aboutResult.html
...
<body>
<h1>Hello, About</h1>
<div id="root"></div>
<script src="./public/about_bundle.js"></script>
<a href="./index.html">index</a>
<script src="about_bundle.js"></script>
</body>
이를 살펴보면 제일 하단에 번들링 된 결과가 추가된 것을 확인할 수 있습니다. 이것으로 기나긴 글을 마치도록 하겠습니다.
웹팩의 설치부터 mode, entry, output, loader, plugin 설정하는 방법 작성 끝.🙌