Webpack 실습 (6) - Plugin 기본 개념정리


:raising_hand: 개인적인 Webpack 학습 및 공부 내용을 기록하기 위한 포스트입니다.


실무에서 주로 사용하는 대표적인 로더들에 대한 실습을 진행해본다.

1. Plugin 이란 무엇이며 역할은 무엇일까?


loader 를 통해서 파일단위로 다양한 처리를 하였다면 plugin 을 통해서는 bundling 된 결과물을 처리한다. 예를 들면 bundlingjavascript 를 난독화하거나 특정 텍스트를 추출 하는 용도이다.

2. Plugin 구현 실습


현재 webpack 공식 문서를 보면 plugin 에 대한 custom 예제들을 많이 찾을 수 있다.

공식 문서에 있는 예제를 하나 가져와서 프로젝트에 만들어 보았다.

//my-webpack-plugin.js

// Custom 화 한 plugin

class MyWebpackPlugin {
  apply(compiler) {
    // plugin 이 종료되면 2번째 인자로 준 Callback 함수가 실행된다.
    compiler.hooks.done.tap("My Plugin", (stats) => {
      console.log("MyPlugin: done");
    });
  }
}

module.exports = MyPlugin;

my-webpack-plugin.js 파일에 위와 같이 클레스를 정의한다. 위 클레스는 apply 함수에서 제공하는 complier 를 통해 webpack build 가 끝나는 시점에 2번째 인자로 준 callback 함수가 실행되도록 할 계획으로 작성된 코드이다.

complier 에 대해서는 정확히 이해가 되지 않아 좀 더 찾아봐서 추후에 따로 정리를 한번 해야될것 같다…ㅠ

우선 plugin 을 대신할 js 파일을 만들었으므로, webpack.config.js 에 위 jsplugin 처럼 실행하도록 설정을 바꿔보자

const path = require("path");
const MyWebpackPlugin = require("./my-webpack-plugin");

module.exports = {
  mode: "development",
  entry: {
    main: "./src/app.js",
  },
  output: {
    path: path.resolve("./dist"),
    filename: "[name].js",
  },
  module: {
  ...
  plugins: [
    new MyWebpackPlugin(), // Class 객체 생성
  ],
};

loader 에 대한 설정을 modules 에 작성하였다면, pluginplugins 에 작성하면 된다. my-webpack-plugin.js 에서 작성한 class 에 대한 객체를 new 를 통해 생성한다.

그 후 build 를 하면 어떻게 될까?

결과

image

loader 를 실습할때는 module에 설정한 동작이 파일하나 혹은 여러개에 대해 반복 되었지만, plugin 의 경우 한번만 동작하는 것을 볼 수 있다.

이유는 pluginbundling 된 결과물을 대상으로 즉, 우리가 자주 했던 main.js ? 라 생각하면 될것 같다. 어쨋든 이런 결과물을 대상으로 동작한다고 한다.

따라서, 우리가 실습에서 생성하는 결과물 파일은 main.js 하나이기 때문에 한번만 동작하는 것을 확인할 수 있었다.

3. BannerPlugin 의 Compliation 인자


BannerPlugin 코드(Webpack 의 내장 플러그인) 를 참고한 예제 코드를 가져와 보았다.

// Custom 화 한 plugin

class MyWebpackPlugin {
  apply(compiler) {
    // plugin 이 종료되면 2번째 인자로 준 Callback 함수가 실행된다.
    // compiler.hooks.done.tap("My Plugin", (stats) => {
    //   console.log("MyPlugin: done");
    // });

    // compiler.plugin() 함수로 후처리한다
    compiler.plugin("emit", (compilation, callback) => {
      // Compliation 을 통해서 Webpack 이 번들링 한 결과물에 대한 접근을 할 수 있다.
      const source = compilation.assets["main.js"].source();
      console.log(source);
      callback();
    });
  }
}

module.exports = MyWebpackPlugin;

source 를 찍어보니 진짜 번들링된것 같은 로그를 볼 수 있었다.

image

그렇다면 실습으로 이번엔 해당 소스를 재정의 하여 bundling 된 결과 상단에 지정한 문자열을 추가하도록 하는 소스로 실습하였다.

compiler.plugin("emit", (compilation, callback) => {
  // Compliation 을 통해서 Webpack 이 번들링 한 결과물에 대한 접근을 할 수 있다.
  const source = compilation.assets["main.js"].source();
  // 번들링 된 main.js 파일 상단에 banner 문자열이 추가되도록 하는 소스
  compilation.assets["main.js"].source = () => {
    const banner = [
      "/**",
      " * 이것은 BannerPlugin이 처리한 결과입니다.",
      " * Build Date: 2022-01-19",
      " */",
    ].join("\n");
    return banner + "\n" + source;
  };
  callback();
});
결과

image

위처럼 결과물인 main.js 파일 최상단에 입력한 banner 내용이 들어가 있는 것을 볼 수 있다.

4. 최종 정리


결과적으로 plugin 이란 webpack 이 번들링을 통해 여러개의 파일을 합치게 된 결과물에 대한 후처리 를 한다고 이해하면 될 것 같다.

image

즉, 위 사진에서 빨간색으로 표시한 부분에서 최종적으로 번들링된 각각의 파일들에 대하여 원하는대로 처리를 한다고 이해하면 될 것 같다.

참고 사이트


https://jeonghwan-kim.github.io/series/2019/12/10/frontend-dev-env-webpack-basic.html