webpack 공식 홈페이지와 김정환님의 프론트엔드 개발환경 이해를 참고하여 작성했습니다.
loader가 파일 단위로 처리하는 반면 plugin은 번들된 결과물을 처리한다. 번들된 자바스크립트를 난독화 한다거나 특정 텍스트를 추출하는 용도로 사용한다.
plugin은 arguments/options을 사용할 수 있으므로
webpack configuration에서plugins
속성값을 new instance
로 줘야한다.
webpack.config.js
//HtmlWebpackPlugin is installed via npm
const HtmlWebpackPlugin = require('html-webpack-plugin');
//to access built-in plugins
const webpack = require('webpack');
const path = require('path');
module.exports = {
...
plugins: [ // new Instance로 속성값 주기
new webpack.ProgressPlugin(),
new HtmlWebpackPlugin({template: './src/index.html'})
]
};
생성 된 각 chunk의 상단에 배너를 추가합니다.
결과물에 빌드 정보나 커밋 버전같은 걸 추가할 수 있다.
webpack.config.js
import webpack from 'webpack';
// string
new webpack.BannerPlugin({
banner: 'hello world' // 배너 정보 문자열
});
// function
new webpack.BannerPlugin({
banner: (yourVariable) => { return `yourVariable: ${yourVariable}`; }
});
Since webpack 2.5.0, placeholders are evaluated in the banner string:
new webpack.BannerPlugin({
banner: 'fullhash:[fullhash], chunkhash:[chunkhash], name:[name], filebase:[filebase], query:[query], file:[file]'
});
DefinePlugin을 사용하면 컴파일 타임에 구성 할 수있는 전역 상수 문자열를 만들 수 있습니다. 이 전역 상수 문자열를 통해development와 production 빌드간에 서로 다른 동작을 하도록 설정할 수 있다.
환경을 CLI로 조작할려면
NODE_ENV=develop || production
을 해당 명령 앞에 적어주면 된다. 하지만
window환경에서는 에러가 난다. 이를 해결하기 위해 cross-env패키지를 설치해 줘야한다. 그다음 개발환경을 조작하는 명령 앞에cross-env NODE_ENV=NODE_ENV=develop || production
을 붙여 주면된다. 필자는package.json
파일에 script를 추가해줬다
npm i cross-env
package.json"scripts": { "build": "webpack --progress", "prodbuild": "cross-env NODE_ENV=production npm run build" },
DefinePlugin몇가지 규칙이 있다.
//webpack.config.js
const webpack = require("webpack")
module.export = {
...
plugins:[
new webpack.DefinePlugin({
//*전역 상수*
PRODUCTION: JSON.stringify(true),
VERSION: JSON.stringify('5fa3b9'),
BROWSER_SUPPORTS_HTML5: true,
TWO: '1+1',
'typeof window': JSON.stringify('object'),
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
});
]
}
---------------------------------------------
//app.js
// 전역 상수 활용
console.log('Running App version ' + VERSION);
if(!BROWSER_SUPPORTS_HTML5) require('html5shiv');
if (!PRODUCTION) {
console.log('Debug info');
}
if (PRODUCTION) {
console.log('Production log');
}
HtmlWebpackPlugin은 웹팩 번들을 제공하는 HTML 파일 생성을 단순화합니다.
entry point가 있으면 생성된 HTML파일에 <script>
tags를 삽입해준다.
output point에 css파일이 있으면 (MiniCssExtractPlugin로 인해 css가 추출된 경우) 생성된 HTML파일의 <header>
에 <link>
tags를 삽입해준다
npm install --save-dev html-webpack-plugin
var HtmlWebpackPlugin = require('html-webpack-plugin');
var path = require('path');
module.exports = {
...
plugins: [new HtmlWebpackPlugin()]
};
npm run build
를 해주면 dist/index.html
파일을 생성한다.
// src/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>webpack App</title>
</head>
<body>
<script src="index_bundle.js"></script>
</body>
</html>
환경을 CLI로 조작할려면
NODE_ENV=develop || production
을 해당 명령 앞에 적어주면 된다. 하지만
window환경에서는 에러가 난다. 이를 해결하기 위해 cross-env패키지를 설치해 줘야한다. 그다음 개발환경을 조작하는 명령 앞에cross-env NODE_ENV=NODE_ENV=develop || production
을 붙여 주면된다. 필자는package.json
파일에 script를 추가해줬다
package.json"scripts": { "build": "webpack --progress", "prodbuild": "cross-env NODE_ENV=production npm run build" },
src/index.html:
<!DOCTYPE html>
<html>
<head>
<title>타이틀<%= env %></title>
</head>
<body>
...
<!-- <script src="main.js"></script> -->
</body>
</html>
title tag에 ejs문법을
<%= env %>
을 사용하여 전달받은 env 값을 출력한다. HtmlWebpackPlugin은 이러한 변수에 데이터를 주입시켜 동적으로 HTML 코드를 생성한다.
뿐만 아니라 웹팩으로 빌드한 결과물을 자동으로 로딩하는 코드를 주입해 준다.
HtmlWebpackPlugin option
webpack.config.js:
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports {
plugins: [
new HtmlWebpackPlugin({
// 템플릿 경로를 지정
template: './src/index.html',
// 템플릿에 주입할 파라매터 변수 지정
templateParameters: {
env: process.env.NODE_ENV === 'development' ? '(개발용)' : '',
},
minify:
process.env.NODE_ENV === "production"
? {
collapseWhitespace: true, // 빈칸 제거
removeComments: true // 주석 제거
}
: false,
hash: process.env.NODE_ENV === "production"
})
]
}
이렇게 설정하고 development build
를 해주면 아래 코드와 같이 새로운 script
tag가 삽입된다. 또한 ejs문법 부분에 (개발용)
문자열이 적용된 것도 볼 수 있다
npm build
<!DOCTYPE html>
<html>
<head>
...
<title>검색(개발용)</title>
</head>
<body>
...
<!-- <script src="dist/main.js"></script> -->
<script type="text/javascript" src="main.js"></script></body>
</html>
title태그에서 (개발용)
이 없는 것을 볼 수 있다.
script태그가 추가되었다.
npm prodbuild
<!DOCTYPE html>
<html>
...
<title>검색</title>
</head>
<body>
...
<script type="text/javascript" src="main.js?d130f7718ede01c57909"></script>
</body>
</html>
개발 환경에서는 CSS를 하나의 모듈로 처리해도 상관없지만 프로덕션 환경에서는 분리하는 것이 효과적이다.
스타일시트가 점점 많아지면 번들된 파일의 용량도 커지기 때문에 별도의 css파일로 만들어 역할에 따라 파일을 분리하는게 좋다.
여러 작은 파일을 동시에 다운로드하는 것이 큰 파일 하나 받는 것보다 빠르다.
번들된 js파일에서 css를 별도의 파일로 추출한다.
css를 포함하는 js파일 당 1개의 css파일을 생성한다.
MiniCssExtractPlugin의 결과로 인해 css파일이 생기면 HtmlWebpackPlugin에서 css에 대한
link
태그를 html에 삽입하게 된다.
npm install --save-dev mini-css-extract-plugin
style.css
body {
background: green;
}
component.js
import './style.css';
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
// MiniCssExtractPlugin.loader 설정
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
plugins: [new MiniCssExtractPlugin()],
};
MiniCssExtractPlugin은 css에 적용하기 위해서 loader가 필요한데 이것이 바로
MiniCssExtractPlugin.loader
이다 loader이기 때문에 module.rules에 추가되어야한다.
배포환경 조건에 따라 설정을 해주기위해 plugin에filter(Boolean)
을 사용했다.
webpack.config.js
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
process.env.NODE_ENV = process.env.NODE_ENV || "development";
module.exports = {
mode: process.env.NODE_ENV,
...
module: {
rules: [
{
test: /\.css$/,
use: [
// 배포 환경일 경우에만 적용
process.env.NODE_ENV === "production"
? MiniCssExtractPlugin.loader // 프로덕션 환경
: "style-loader", // 개발 환경
"css-loader",
],
},
],
},
plugins: [
...
,
// 배포 환경일 경우에만 적용
process.env.NODE_ENV === "production" &&
new MiniCssExtractPlugin({ filename: "[name].css" }),
].filter(Boolean),
};
빌드 이전 결과물을 제거하는 플러그인이다.
output엔트리에 해당되는 파일들을 모두 삭제한다.
Cleaning up the /dist folder
npm install -D clean-webpack-plugin
const { CleanWebpackPlugin } = require("clean-webpack-plugin")
module.exports = {
...
plugins: [new CleanWebpackPlugin()],
}