ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자주 사용하는 플러그인 - 웹팩(Webpack) 기본편 | 김정환
    Front-end/개발환경 2020. 6. 7. 20:23
    반응형

    1. BannerPlugin

    MyPlugin와 비슷한 것이 BannerPlugin이다. 결과물에 빌드 정보나 커밋 버전같은 걸 추가할 수 있다.

     

    webpack.config.js :

    const webpack = require('webpack');
    
    module.exports = {
      plugins: [
        new webpack.BannerPlugin({
          banner: '이것은 배너 입니다',
        })
      ]
    }

    생성자 함수에 전달하는 옵션 객체의 banner 속성의 값으로 문자열을 전달한다. 웹팩 컴파일 타임에 얻을 수 있는 정보, 가령 빌드 시간이나 커밋정보를 전달하기위해 함수로 전달할 수도 있다.

     

    webpack.config.js 

        new webpack.BannerPlugin({
          banner: () => `빌드 날짜: ${new Date().toLocaleString()}`
        })
      ]
    }

    배너 정보가 많다면 별로 파일로 분리하자.

     

    webpack.config.js : 

    const banner = require('./banner.js');
    
    new webpack.BannerPlugin(banner);

    빌드 날짜 외에서 커밋 해쉬와 빌드한 유저 정보까지 추가해 보자.

     

    banner.js :

    const childProcess = require('child_process');
    
    module.exports = function banner() {
      const commit = childProcess.execSync('git rev-parse --short HEAD')
      const user = childProcess.execSync('git config user.name')
      const date = new Date().toLocaleString();
      
      return (
        `commitVersion: ${commit}` +
        `Build Date: ${date}\n` +
        `Author: ${user}`
      );
    }

    * node module 중 'child_process' 을 사용하면 자식 프로세스를 생성하거나 다른 프로세스의 작업을 실행할 수 있다.

    * childProcess.execSync('문자열') : 문자열을 받아서 터미널에 실행해준다.

     

    2. DefinePlugin

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

     

    웹팩은 이러한 환경 정보를 제공하기 위해 DefinePlugin을 제공한다.

     

    webpack.config.js : 

    const webpack = require('webpack');
    
    export default {
      plugins: [
        new webpack.DefinePlugin({}),
      ]
    }

    빈 객체를 전달해도 기본적으로 넣어주는 값이 있다. 노드 환경정보인 process.env.NODE_ENV 인데 웹팩 설정의 mode에 설정한 값이 여기에 들어간다. “development”를 설정했기 때문에 어플리케이션 코드에서 process.env.NODE_ENV 변수로 접근하면 “development” 값을 얻을 수 있다.

     

    app.js :

    console.log(process.env.NODE_ENV) // "development"

    이 외에도 웹팩 컴파일 시간에 결정되는 값을 전역 상수 문자열로 어플리케이션에 주입할 수 있다.

     

    webpack.config.js : 

        new webpack.DefinePlugin({
          TWO: '1+1',
        }),
      ]
    }

    TWO라는 전역 변수에 1+1 이란 코드 조각을 넣었다. 실제 어플리케이션 코드에서 이것을 출력해보면 2가 나올 것이다.

     

    app.js : 

    console.log(TWO); // 2

    코드가 아닌 값을 입력하려면 문자열화 한 뒤 넘긴다.

        new webpack.DefinePlugin({
          VERSION: JSON.stringify('v.1.2.3'),
          PRODUCTION: JSON.stringify(false),
          MAX_COUNT: JSON.stringify(999),
          'api.domain': JSON.stringify('http://dev.api.domain.com'),
        }),
      ]
    }

    app.js :

    console.log(VERSION) // 'v.1.2.3'
    console.log(PRODUCTION) // true
    console.log(MAX_COUNT) // 999
    console.log(api.domain) // 'http://dev.api.domain.com'

    빌드 타임에 결정된 값을 어플리이션에 전달할 때는 이 플러그인을 사용하자.

     

    3. HtmlWebpackPlugin

    이번엔 써드 파티 패키지에 대해 알아보자. HtmlWebpackPlugin은 HTML 파일을 후처리하는데 사용한다. 빌드 타임의 값을 넣거나 코드를 압축할수 있다.

     

    먼저 패키지를 다운로드 한다.

     

    > npm install -D html-webpack-plugin

     

    이 플러그인으로 빌드하면 HTML파일로 아웃풋에 생성될 것이다. index.html 파일을 src/index.html로 옮긴뒤 다음과 같이 작성해 보자.

     

    src/index.html :

    <!DOCTYPE html>
    <html>
      <head>
        <title>타이틀<%= env %></title>
      </head>
      <body>
        <!-- 로딩 스크립트 제거 -->
        <!-- <script src="dist/main.js"></script> -->
      </body>
    </html>

    타이틀 부분에 ejs 문법을 이용하는데 <%= env %> 는 전달받은 env 변수 값을 출력한다. HtmlWebpackPlugin은 이 변수에 데이터를 주입시켜 동적으로 HTML 코드를 생성한다. 뿐만 아니라 웹팩으로 빌드한 결과물을 자동으로 로딩하는 코드를 주입해 준다. 때문에 스크립트 로딩 코드도 제거했다.

     

    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' ? '(개발용)' : '', 
          },
        })
      ]
    }

    환경 변수에 따라 타이틀 명 뒤에 “(개발용)” 문자열을 붙이거나 떼거나 하도록 했다.

     

    > NODE_ENV=development npm run build 빌드 결과 index.html의 타이틀이 “타이틀(개발용)”으로 나온다.

    > NODE_ENV=production npm run build 빌드결과 “타이틀”로 나온다.

     

    개발 환경과 달리 운영 환경에서는 파일을 압축하고 불필요한 주석을 제거하는 것이 좋다.

     

    webpack.config.js :

        new HtmlWebpackPlugin({
          minify: process.env.NODE_ENV === 'production' ? { 
            collapseWhitespace: true, // 빈칸 제거 
            removeComments: true, // 주석 제거 
          } : false,
        }
      ]
    }

    문서에는 minifiy 옵션이 웹팩 버전 3 기준으로 되어 있다

     

    환경변수에 따라 minify 옵션을 켰다. 

    > NODE_ENV=production npm run build 빌드 결과 index.html의 주석이 제거 되고 코드가 압축된다.

     

    정적파일을 배포하면 즉각 브라우져에 반영되지 않는 경우가 있다. 브라우져 캐쉬가 원인일 경우가 있는데 이를 위한 예방 옵션도 있다.

     

    webpack.config.js :

        new HtmlWebpackPlugin({
          hash: true, // 정적 파일을 불러올때 쿼리문자열에 웹팩 해쉬값을 추가한다
        })
      ]
    }

    * hash : true 옵션을 추가하면 빌드할 시 생성하는 해쉬값을 정적파일 로딩 주소의 쿼리 문자열로 붙여서 HTML을 생성한다.

     

    4. CleanWebpackPlugin

    CleanWebpackPlugin은 빌드 이전 결과물을 제거하는 플러그인이다. 빌드 결과물은 아웃풋 경로에 모이는데 과거 파일이 남아 있을수 있다. 이전 빌드내용이 덮여 씌여지면 상관없지만 그렇지 않으면 아웃풋 폴더에 여전히 남아 있을 수 있다.

     

    임시로 아웃풋 폴더에 foo.js 파일을 만든 후 다시 빌드하면 여전히 파일이 남아 있다.

    이러한 현상을 CleanWebpackPlugin으로 해결해 보자. 먼저 패키지를 설치한다.

     

    > npm install -D clean-webpack-plugin

     

    웹팩 설정을 추가한다.

     

    webpack.config.js :

    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    
    module.exports = {
      plugins: [
        new CleanWebpackPlugin(),
      ]
    }

    * clean-webpack-plugin은 다른 플러그인과 다르게 default로 export 되어 있지 않기 때문에 const { 상수명 } 으로 작성한다.

     

    > npm run build 빌드 결과 foo.js가 깨끗히 사라졌다.

     

    아웃풋 폴더인 dist 폴더가 모두 삭제된후 결과물이 생성되었기 때문이다.

     

    5. MiniCssExtractPlugin

    스타일시트가 점점 많아지면 하나의 자바스크립트 결과물로 만드는 것이 부담일 수 있다. 번들 결과에서 스트일시트 코드만 뽑아서 별도의 CSS 파일로 만들어 역할에 따라 파일을 분리하는 것이 좋다. 브라우져에서 큰 파일 하나를 내려받는 것 보다, 여러 개의 작은 파일을 동시에 다운로드하는 것이 더 빠르다. 개발 환경에서는 CSS를 하나의 모듈로 처리해도 상관없지만 프로덕션 환경에서는 분리하는 것이 효과적이다. 

    MiniCssExtractPlugin은 CSS를 별로 파일로 뽑아내는 플러그인이다. 먼저 패키지를 설치한다.

     

    > npm install -D mini-css-extract-plugin

     

    웹팩 설정을 추가한다.

     

    webpack.config.js :

    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    
    module.exports = {
      plugins: [
        ...(
          process.env.NODE_ENV === 'production' 
          ? [ new MiniCssExtractPlugin({filename: '[name].css'}) ]
          : []
        ),
      ],
    }

    나머지 연산자로 전달해서 프로덕션 환경일 경우만 이 플러그인을 추가했다. filename에 설정한 값으로 아웃풋 경로에 CSS 파일이 생성될 것이다.

    * [name]은 파일의 원본명을 가져온다.

     

    개발 환경에서는 css-loader에의해 자바스크립트 모듈로 변경된 스타일시트를 적용하기위해 style-loader를 사용했다. 반면 프로덕션 환경에서는 별도의 CSS 파일으로 추출하는 플러그인을 적용했으므로 다른 로더가 필요하다.

    module.exports = {
      module: {
        rules: [{
          test: /\.css$/,
          use: [
            process.env.NODE_ENV === 'production' 
            ? MiniCssExtractPlugin.loader  // 프로덕션 환경
            : 'style-loader',  // 개발 환경
            'css-loader'
          ],
        }]
      }
    }

    프로덕션 환경일 경우는 플러그인에서 제공하는 MiniCssExtractPlugin.loader 로더를 추가한다.

     

    > NODE_ENV=production npm run build 빌드 결과 dist/main.css가 생성되었고 index.html에 이 파일을 로딩하는 코드가 추가되었다.


    SUMMARY

    # BannerPlugin

    : 번들링된 결과물 상단에 빌드 정보를 추가한다. 

     

    # DefinePlugin

    : 빌드 타임에 결정되는 환경 변수를 어플리케이션 단에 주입하기 위해서 사용한다.  *ex) API 주소

     

    # HtmlWebpackPlugin

    : HTML 파일을 빌드 과정에 추가할 수 있어서 동적으로 생성되는 Javascript와 CSS, 빌드 타임에 결정되는 값을 템플릿 파일에 넣어서 HTML 파일을 동적으로 만들어 준다.

     

    # CleanWebpackPlugin

    : 빌드할 때마다 output 폴더(/dist)를 삭제해준다.

     

    # MiniCssExtractPlugin

    : 번들된 자바스크립트 코드에서 CSS 파일만 따로 추출해서 CSS 파일을 만들어준다.

     


     

    TODO.1

    아래 플러그인을 추가해서 번들 결과를 만들어 보세요.

     

    1. BannerPlugin: 결과물에 빌드 시간을 출력하세요.

    더보기

    webpack.config.js : 

    const webpack = require('webpack');
    const childProcess = require('child_process');
    
    module.exports = {
      plugins: [
        new webpack.BannerPlugin({
          banner: `
            Build Date : ${new Date().toLocaleDateString()}
            Commit Version : ${childProcess.execSync('git rev-parse --short HEAD')}
            Author : ${childProcess.execSync('git config user.name')}
          `
        })
      ]
     };

     

    2. HtmlWebpackPlugin: 동적으로 html 파일을 생성하세요.

    더보기

    > npm install html-webpack-plugin

     

    webpack.config.js : 

    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
      plugins: [
        new HtmlWebpackPlugin({
          template: './src/index.html',
          minify: process.env.NODE_ENV === "producttion" ? {
            collapseWhitespace: true,
            removeComments: true,
          } : false,
        })
      ]
    };

     

    3. CleanWebpackPlugin: 빌드 전에 아웃풋 폴더를 깨끗히 정리하세요.

    더보기

    > npm install clean-webpack-plugin

     

    webpack.config.js : 

    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    
    module.exports = {
      plugins: [
        new CleanWebpackPlugin();
      ]
    };

     

    4. MiniCssExtractPlugin: 모듈에서 css 파일을 분리하세요.

    더보기

    > npm install mini-css-extract-plugin

     

    webpack.config.js : 

    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    
    module.exports = {
      plugins: [
        ...(process.env.NODE_ENV === "production"
          ? [new MiniCssExtractPlugin({ filename: '[name].css' })]
          : []
        )
      ]
    }

    TODO.2

    1. HtmlWebpackPlugin에서 빌드 환경을 주입하도록 웹팩을 구성하세요

    더보기

    /src/index.html :

    <title>검색 <%= env %></title>

     

    webpack.config.js : 

    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
      plugins: [
        new HtmlWebpackPlugin({
          templateParameters: {
            env: process.env.NODE_ENV === "development" ? "(개발용)" : "",
          },
        })
      ]
    };

     

    2. HtmlWebpackPlugin에서 엔트리 포인트(main.css)를 로딩하도록 웹팩을 구성하세요

    더보기

    webpack.config.js : 

    module.exports = {
      module: {
        rules: [
          {
            test: /\.css$/,
            use: [
              process.env.NODE_ENV === "production"
              : MiniCssExtractPlugin.loader
              : "style-loader", "css-loader"
            ]
          }
        ]
      }
    }
    반응형

    댓글

Luster Sun