Webpack - Plugin

Jung taeWoong·2021년 9월 30일
1

개발환경

목록 보기
3/8
post-thumbnail

Plugin

번들된 결과물을 처리
번들된 자바스크립트를 난독화 한다거나 특정 텍스트를 추출하는 용도로 사용됨

  • 로더는 여러 파일에 대해 각각 실행했다면 플러그인은 하나로 뭉쳐논 번들파일에 대하여 딱 한번 실행됨(결과물 처리)

커스텀 플러그인 예제

// my-webpack-plugin.js
// 플러그인은 class로 작성
class MyWebpackPlugin {
  apply(compiler) {
    compiler.plugin('emit', (compilation, callback) => {
      // source() => 웹팩이 번들링한 결과물의 소스코드를 가져오는 함수
      // compilation 객체를 이용해서 웹팩이 번들링한 결과물에 접근할수 있다
      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;

// webpack.config.js
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 생성자로 인스턴스 생성
    new MyWebpackPlugin()
  ]
}

자주 사용하는 Plugin

  • 개발하면서 플러그인을 직접 작성할 일은 거의 전무하다.
  • 웹팩에서 직접 제공하는 플러그인을 사용하거나 써드파티 라이브러리를 찾아 사용하는데 자주 사용되는 플러그인들을 알아보자

1. BannerPlugin

번들링된 결과물 상단에 빌드 정보나 커밋 버전 등을 추가할 수 있다.

webpack.config.js

const path = require('path');
// 웹팩에서 직접 제공하는 플러그인으로 웹팩을 불러와야한다.
const webpack = require('webpack');
// 터미널 명령어를 실행할수 있는 모듈
const childProcess = require('child_process');

module.exports = {
  mode: 'development',
  entry: {
    main: './src/app.js'
  },
  output: {
    path: path.resolve('./dist'),
    filename: '[name].js'
  },
  module: {},
  plugins: [new webpack.BannerPlugin({
    banner: `
    Build Date: ${new Date().toLocaleString()}
    Commit Version: ${childProcess.execSync('git rev-parse --short HEAD')}
    Author: ${childProcess.execSync('git config user.name')}
    `
  })]
}

2. DefinePlugin

빌드타임에 결정되는 환경변수를 어플리케이션 단에 주입하기 위한 플러그인

  • 어플리케이션은 개발환경과 운영환경으로 나눠서 운영함
  • 가령 환경에 따라 API 서버 주소가 다를 수 있다.
  • 같은 소스 코드를 두 환경에 배포하기 위해서는 이러한 환경 의존적인 정보를 소스가 아닌 곳에서 관리하는 것이 좋다.
  • 배포할 때마다 코드를 수정하는 것은 곤란하기 때문
  • 이러한 환경 정보를 제공하기 위해 DefinePlugin을 제공한다.

webpack.config.js

const path = require('path');
// 마찬가지로 웹팩에서 직접 제공하는 플러그인으로 웹팩을 불러와야한다.
const webpack = require('webpack');

module.exports = {
  mode: 'development', // 개발환경
  entry: {
    main: './src/app.js'
  },
  output: {
    path: path.resolve('./dist'),
    filename: '[name].js'
  },
  module: {},
  plugins: [new webpack.DefinePlugin({
    // 직접 환경변수 설정 가능
    CODE_TWO: '1+1', // CODE
    STRING_TWO: JSON.stringify('1+1'),  // 문자열
    'api.domain': JSON.stringify('http://dev.api.domain.com') // 객체타입
  })]
}


// app.js
/*설정한 환경변수 접근 가능*/
console.log('process.env.NODE_ENV', process.env.NODE_ENV); // development
console.log('CODE_TWO', CODE_TWO); // 2
console.log('STRING_TWO', STRING_TWO); // 1+1
console.log('api.domain', api.domain); // http://dev.api.domain.com

3. HtmlTemplatePlugin

빌드 타임에 HTML도 포함시키는 플러그인

  • 써드파티 패키지
  • HTML 파일을 후처리하는데 사용한다.
    • html파일을 src 내부로 옮겨주어야 한다.
  • 빌드 타임의 값을 넣거나 코드를 압축할 수 있다.

설치

$ npm install -D html-webpack-plugin // 설치 필요

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plguin');

module.exports = {
  mode: 'development',
  entry: {
    main: './src/app.js'
  },
  output: {
    path: path.resolve('./dist'),
    filename: '[name].js'
  },
  module: {},
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html', // 템플릿 경로
      // 템플릿에 넣어줄 변수 값을 전달
      templateParameters: {
        env: process.env.NODE_ENV === 'development' ? '(개발용)' : ''
      },
      // html 압축 (개발 환경일 때만)
      minify: process.env.NODE_ENV === 'production' ? {
        collapseWhitespace: true, // 빈칸 제거
        removeComments: true, // 주석 제거
       } : false
    })
  ]
}

src/index.html

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <!-- EJS문법: env를 넣을수 있는 템플릿 문법  -->
  <!-- Webpack에서 HtmlTemplatePlugin으로 env의 값을 넣어줄 수 있다. -->
  <title>Document<%= env %></title>
</head>
<body>
</body>
</html>
  • NODE_ENV=development npm run build

오류: 'NODE_ENV'은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는 배치파일이 아닙니다.

$ npm install -g win-node-env 
// node-env를 글로벌로 설치해서 해결

4. CleanWebpackPlugin

빌드 이전 결과물을 제거하는 플러그인

  • 빌드 결과물은 아웃풋 경로에 모이는데 과거 파일이 남아있을수 있다.
  • 써드 파티 패키지 플러그인

설치

$ npm install -D clean-webpack-plugin // 설치 필요

webpack.config.js

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

module.exports = {
  mode: 'development',
  entry: {
    main: './src/app.js'
  },
  output: {
    path: path.resolve('./dist'),
    filename: '[name].js'
  },
  module: {},
  plugins: [new CleanWebpackPlugin()]
}

5. MiniCssExtractPlugin

번들된 자바스크립트 코드에서 CSS를 별도 파일로 뽑아내는 플러그인

  • 스타일시트가 많아질수록 하나의 자바스크립트 결과물로 만드는 것은 부담된다.
  • 번들 결과에서 스타일시트 코드만 뽑아서 별도의 CSS 파일로 만들어 역할에 따라 파일을 분리하는 것이 좋음
  • 브라우저에서는 큰 파일 하나보다 작은 파일 여러개를 다운로드 하는것이 더 빠르다.
  • 개발환경은 상관없지만 배포환경에서는 분리하는것이 효과적

설치

$ npm install -D mini-css-extract-plugin // 설치 필요

webpack.config.js

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plguin'); 

module.exports = {
  mode: 'development',
  entry: {
    main: './src/app.js'
  },
  output: {
    path: path.resolve('./dist'),
    filename: '[name].js'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        // MiniCSSExtractPlugin을 사용하려면 style-loader 대신에 자체 로더를 사용해야한다.
        use: [
          process.env.NODE_ENV === 'production'
           ? MiniCssExtractPlugin.loader
           : 'style-loader',
           'css-loader'
        ]
      }
      ]
  },
  // 배포 환경일때만 설정
  plugins: [...(process.env.NODE_ENV === 'production'
        ? [new MiniCssExtractPlugin({filename: '[name].css'})]
        : []
    )
}

'[name]' => 원본 파일이름으로 설정. 아니면 해시 값으로 설정됨

profile
Front-End 😲

0개의 댓글