플러그인

로더가 파일단위로 처리하는 반면 플러그인은 번들된 결과물을 처리할때 사용한다. 번들된 자바스크립트를 난독화 하거나 특정 텍스트를 추출할하는 용도로도 사용이 가능하다.


커스텀 플러그인 만들기

로더는 함수 기반이었지만 플러그인은 클래스 기반으로 작성한다.

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
// plugin.js

class MyPlugin {
apply(compiler) {
// 플러그인이 완료 된 후 실행될 콜백함수를 지정한다.
compiler.hooks.done.tap('My Plugin', stats => {
console.log('MyPlugin: done');
});

// 실제로 플러그인이 처리할 코드가 들어가는 부분이다.
compiler.plugin('emit', (compliation, callback) => {
// compliation.assets['main.js'].source();를 통해서 번들링 된 파일을 가져올수 있다.
const source = compliation.assets['main.js'].source();

// source 메소드를 재정의 하고 있다.
compliation.assets['main.js'].source = () => {
const banner = [
'/**',
' * 이것은 BannerPlugin이 처리한 결과입니다.',
' * Build Date: 2019-10-10',
' */'
].join('\n');
return banner + '\n\n' + source;
}

callback();
});
}
}

module.exports = MyPlugin;
1
2
3
4
5
6
7
8
9
10
// webpack.config.js

const MyPlugin = require('./plugin.js');

module.exports = {
// ...
plugins: [
new MyPlugin()
]
}

웹팩에 plugins 배열에 등록해준다. 직접 클래스를 생성후에 넣어준다.

플러그인 또한 로더처럼 커스텀 플러그인을 만들 일을 거의 없다.


자주사용되는 플러그인

BannerPlugin

결과물에 빌드 정보다 커밋 버전 등을 추가할때 주로 사용한다. 말그대로 배너를 추가할때 사용한다.
웹팩이 기본적으로 제공해주기 때문에 따로 설치할 필요가 없다.

1
2
3
4
5
6
7
8
9
10
11
12
// webpack.config.js

const webpack = require('webpack');

plugins: [
new webpack.BannerPlugin({
banner: `
Build Date: ${new Date().toLocaleString()}
Commit Version: ${childProcess.execSync('git config user.name')}
`
})
]

DefinePlugin

웹팩에서 제공하는 DefinePlugin은 모든 자바스크립트 코드에서 접근이 가능한 전역 변수를 선언하기 위해서 사용되는 플러그인이다. 사용방법은 webpack.DefinePlugin의 생성자에 전역 변수로 사용할 값을 객체 형태로 넘겨준다.

1
2
3
4
5
6
7
8
9
10
11
// webpack.config.js

const webpack = require('webpack');

plugins: [
new webpack.DefinePlugin({
TWO: '1+1',
TWO2: JSON.stringify('1+1'),
'api.domian': JSON.stringify('http://naver.com')
})
]

주의 할 점은 값이 문자열이 아니라 계산식이라는 것이다. 첫번째 값이 ‘1+1’은 문자열이 아니라 계산되어 2라는 값이 TWO에 저장된다. ‘1+1’이라는 문자열을 사용하고 싶으면 JSON.stringify를 사용하여야 한다.
키가 api.domian 이런식으로 등록하면 실제 사용할때는 객체 형식으로 접근이 가능하다.

1
2
3
4
5
// main.js

console.log(TWO); // 2
console.log(TWO2); // 1+1
console.log(api.domain); // http://naver.com

노드의 process 객체는 기본적으로 전역적으로 사용할수 있도록 등록이 되어 있다.

1
2
3
// main.js

console.log(process.env);

HtmlWebpackPlugin

서드파티로 제공하는 HtmlWebpackPlugin는 HTML 파일을 후처할때 사용한다. 이 플러그인을 사용하면 HTML도 빌드의 과정에 포함 시킬수 있다.

1
npm install -D html-webpack-plugin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// webpack.config.js

const HtmlWebpackPlugin = requrie('html-webpack-plugin');

plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
templateParameters: {
'param': 'value'
},
minify: {
collapseWhitespace: true,
removeComments: true
}
})
]
  • template : index.html의 경로를 적어준다. 빌드 후에 output 경로에 index.html 생성이 된다. 번들링된 자바스크립트 경로도 자동으로 index.html에 추가되기때문에 수동으로 작성할 필요가 없어진다.
  • templateParameters: index.html에 파라미터를 전달할수 있다. <%= 파라미터명 %> 으로 값을 가져올수 있다.
    1
    2
    3
    <html>
    <%= param %>
    <html>
  • minify: 말그대로 코드를 경량화 하기 위한 옵션이다.
    • collapseWhitespace: value가 true로 설정 하면 모든 빈칸을 제거해준다.
    • removeComments: value가 true이면 모든 주석을 제거해준다.

CleanWebpackPlugin

서드파티로 제공하는 CleanWebpackPlugin는 빌드 이전 결과물을 모두 제거해 주는 플러그인다(output 폴더를 모두 삭제 후에 빌드가 된다). 해당 플러그인은 export시에 객체로 감싸기 때문에 { CleanWebpackPlugin }으로 사용해야 한다.

1
npm install -D clean-webpack-plugin
1
2
3
4
5
6
7
// webpack.config.js

const { CleanWebpackPlugin } = require('clean-webpack-plugin');

plugins: [
new CleanWebpackPlugin()
]

MiniCssExtractPlugin

스타일 시트의 양이 많을때 자바스크립트 하나로 결과물을 모두 번들링 하게 되면 부담이 커진다. 번들 결과에서 스타일시트 코드만 뽑아서 별도의 css 파일로 관리 할수 있다. 최종 결과물이 css 파일하나, js 파일 하나가 된다(물론 그 이상도 만들수 있다).
개발 모드일때는 하나의 js로 하는게 작업에 좋다고 한다. 배포시에만 설정하도록 해보자.

1
npm install mini-css-extract-plugin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// webpack.config.js
const MiniCssExtracPlugin = require('mini-css-extract-plugin');
module: {
rules: [
{
test: /\.css$/,
use: [
process.env.NODE_ENV === 'development'
? MiniCssExtracPlugin.loader
: 'style-loader',
'css-loader'
]
}
]
},
plugins: [
...(
process.env.NODE_ENV === 'development'
? [new MiniCssExtracPlugin({ filename: '[name].css' })]
: []
)
]

위에 코드에서도 확인 할수 있듯이 MiniCssExtracPlugin를 사용하려면 loader 또한 MiniCssExtracPlugin.loader를 사용하여야 한다.