플러그인
웹팩에서 알아야 할 마지막 기본 개념이 플러그인이다.
1) 플러그인의 역할
로더가 파일 단위로 처리하는 반면, 플러그인은 번들된 결과물을 처리한다.
번들된 자바스크립트를 난독화한다거나 특정 텍스트를 추출하는 용도로 사용한다.
2) 커스텀 플러그인 만들기
웹팩 문서의 Writing a plugin을 보면 클래스로 플러그인을 정의 하도록 한다. 헬로월드 코드를 가져다 그대로 실행 붙여보자.
- my-webpack-plugin.js
1
2
3
4
5
6
7
8
9
class MyWebpackPlugin {
apply(compiler) {
compiler.hooks.done.tap("My Plugin", stats => {
console.log("MyPlugin: done")
})
}
}
module.exports = MyWebpackPlugin
로더와 다르게 플러그인은 클래스로 제작한다. apply 함수를 구현하면 되는데 이 코드에서는 인자로 받은 compiler 객체 안에 있는 tap() 함수를 사용하는 코드다. 플러그인 작업이 완료되는(done) 시점에 로그를 찍는 코드인것 같다.
플러그인을 웹팩 설정에 추가한다.
- webpack.config.js
1
2
3
4
5
const MyWebpackPlugin = require("./myplugin")
module.exports = {
plugins: [new MyWebpackPlugin()],
}
웹팩 설정 객체의 plugins
배열에 설정한다. 클래스로 제공되는 플러그인의 생성자 함수를 실행해서 넘기는 방식이다.
웹팩으로 빌드해 보자.
로그가 찍힌걸 보니 플러그인이 동작했다.
그런데 파일이 여러 개인데 로그는 한 번만 찍혔다. 로더가 파일 하나 혹은 여러 개에 대해 동작하는 반면 플러그인은 하나로 번들링된 결과물을 대상으로 동작 한다.
예제에서는 main.js로 결과물이 하나이기 때문에 플러그인이 한 번만 동작한 것이라 추측할 수 있다.
그러면 어떻게 번들 결과에 접근할 수 있을까?
웹팩 내장 플러그인 BannerPlugin 코드를 참고하자.
- my-webapck-plugin.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MyWebpackPlugin {
// apply(compiler) {
// compiler.hooks.done.tap("My Plugin", stats => {
// console.log("MyPlugin: done")
// })
// compiler.plugin() 함수로 후처리한다
compiler.plugin("emit", (compilation, callback) => {
const source = compilation.assets["main.js"].source()
console.log(source)
callback()
})
}
}
module.exports = MyWebpackPlugin
compiler.plugin() 함수의 두번재 인자 콜백함수는 emit
이벤트가 발생하면 실행되는 녀석인 모양이다. 번들된 결과가 compilation
객체에 들어 있는데 compilation.assets[‘main.js’].source() 함수로 접근할 수 있다. 실행하면 터미널에 번들링된 결과물을 확인할 수 있다.
이걸 이용해서 번들 결과 상단에 아래와 같은 배너를 추가하는 플러그인으로 만들어 보자.
- my-webapck-plugin.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
class MyWebpackPlugin {
apply(compiler) {
// compiler.hooks.done.tap("My Plugin", stats => {
// console.log("MyPlugin: done")
// })
// compiler.plugin() 함수로 후처리한다
compiler.plugin("emit", (compilation, callback) => {
const source = compilation.assets['main.js'].source();
compilation.assets['main.js'].source = () => {
const banner = [
'/**',
' * 이것은 BannerPlugin이 처리한 결과입니다.',
' * Build Date: 2019-10-10',
' */',
''
].join('\n');
return banner + '\n\n' + source;
}
callback();
})
}
}
module.exports = MyWebpackPlugin
번들 소스를 얻어오는 함수 source()를 재정의 했다. 배너 문자열과 기존 소스 코드를 합친 문자열을 반환
하도록 말이다.
빌드하고 결과물을 확인해 보면 다음과 같이 정상적으로 배너 문자열이 추가된 것을 확인할 수 있다.