HTTP 200 OK

Memento mori & Carpe diem

REACT

[webpack] loader & plugin

sjoongh 2022. 3. 30. 19:29

webpack을 사용하던 중 다양한 로더와 플러그인의 역할과 기능에 대해 학습하고자 작성하게 되었다.

 

loader와 plugin의 차이
로더는 파일을 해석하고 변환하는 과정에 관여하는 반면, 플러그인은 해당 결과물의 형태를 바꾸는 역할(기본적인 동작에 추가적인 기능을 제공하는 속성)이다.

▶로더(loader)란?

  • 로더는 빌드 도구를 통한 빌드 과정에서 각 파일을 import 혹은 load할 때 모듈의 소스코드를 변형시키는 전처리 과정을 수행
  • webpack은 기본적으로 JS / JSON 파일만 이해할 수 있어서, other type의 파일을 convert 해줘야 한다

 

▶자주 사용하는 로더 종류

  1. css-loader : css 파일이 js 코드로 변경, 즉 JS파일 내부에서 css파일을 불러오는 역할(내부적으로 번들링된 js파일에 string값으로 css데이터가 존재하게 됨)
  2. style-loader : js로 변경된 css 내용을 동적으로 DOM에 추가(브라우저가 해석하기 위해, 내부적으로 태그를 사용합니다), 따라서 css를 번들링하기 위해서는 css-loader, style-loader를 함께 사용함
  3. file-loader : 파일을 모듈 형태로 지원, webpack output에 파일을 옮겨줌
  4. url-loader : data URI scheme를 이용하여 이미지를 Base64로 인코딩하여 문자열 형태로 소스코드에 넣는 처리를 자동화하는 loader(사용하는 이미지 개수가 많으면 네트워크의 자원을 사용하는 부담이 크고, 성능에 영향을 주기때문에 사용한다.)

▶css 파일을 webpack에서 사용하기

css or scss 파일 생성
/css/main.scss

body{ background-color: yellow; }

main.js

import '../css/main.scss // css적용만을 위해 이름 적용x`

main.js위와 같이 css or scss파일을 main.js파일에 import하여 사용할 수 있도록 도와주는 역할은 loader가 담당합니다.

module: { 
        rules: [{ 
        test: /\.s?css$/, 
        use: [ // 뒤(sass-loader)에서부터 실행된다 && 모듈로 변경된 css를 js로 읽게함 
        'style-loader', 
        'css-loader', 
        'sass-loader'
        ], 
       }
     ]},
// test : 로더를 적용할 파일 유형
// use : 해당 파일에 적용할 로더의 이름

위의 설정으로 해당 프로젝트의 모든 css파일에 대해서 css-loader를 적용하겠다는 의미입니다.

 

webpack에서 로더의 적용은 배열 뒤 -> 앞 방향으로 적용한 순서대로 실행하므로 css와 scss loader를 먼저 적용한 후 style-loader를 맨 앞에 배치해 dom에 적용될 수 있도록 설정해야 합니다.

▶플러그인(plugin)이란?

  • Loader가 파일 단위로 처리하는 반면, Plugin은 번들링 이후의 결과물을 처리
  • Loader는 함수로 정의하지만, Plugin은 클래스로 정의

 

자주 사용하는 플러그인 종류

 

  1. BannerPlugin : 결과물에 build info나 commit version 같은 정보를 추가할 수 있는 플러그인(webpack의 기본 plugin)

예시

/* webpack.config.js */
{
    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')}
            `
        })
    ]
}


/* bundle.js - 결과물 */
/*!
 * 
 *             Build Date : 3/30/2022, 19:52:09 PM
 *             Commit version : ca82fa1
 *
 *             Author : hue
 */
... bundle js code
  1. DefinePlugin : compile time에 코드에 있는 특정 변수를 다른 값이나 표현으로 바꿀 수 있다
    • phase 환경 마다 상이한 정보들을 관리할 때 유용
    • 생성시 빈 객채를 전달해도 기본적으로 process.env.NODE_ENV 값은 넣어준다
    • process.env.NODE_ENV = 'production'
    • process.env.NODE_ENV = 'development'
    • (webpack.config.js의 mode 값을 바라본다)
    • webpack의 기본 plugin

예시

// 컴파일 모드에 따라 자동 주입되는 설정이 다르다.
// mode=development
mode: 'development'
new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }), // 자동 주입

// mode=production
mode: 'production',
new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }), // 자동 주입

// 적용 예시
/* webpack.config.js */
{
    plugins: [
        new webpack.DefinePlugin({
            /* 웹팩의 빌드타임에서 사용가능한 전역 변수로 등록이 된다
               => 런타임에서는 접근이 불가, 하지만 빌드 타임에 전역으로 선언되어 전역 scope를 더럽힐 수 있음
               => 조심해서 사용
            */
            data: JSON.stringify('3+4'),
            api_domain: JSON.stringify('https://dev.api.domain.com')
        })
    ]
}
  1. HtmlTemplatePlugin
  • bundle을 제공하기 위해 HTML 파일 생성을 단순화하는 third party 플러그인
  • template으로 지정한 html에 번들링 된 JS, CSS파일을 자동으로 넣어준다

예시

/* webpack.config.js */
{
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',
            // template 내부에서 ejs문법으로 지정된 변수에 값 매핑
            templateParameters: {
                env: process.env.NODE_ENV === 'development' ? '(개발용)' : ''
            },
            // 생성되는 HTML template를 최소화 하는 옵션
            minify: process.env.NODE_ENV === 'production' ? {
                collapseWhitespace: true, // 공백 제거
                removeComments: true, // 주석 제거
            } : false
        })
    ]
}
  • webpack에서 생성된 번들을 자동으로 import하는 HTML파일을 생성, 매 빌드마다 bundle의 이름을 바꾸게된다면 HTML파일도 변경해주어야 하므로
  • 이것을 통해 HTML파일 생성
  • 개발자가 만든 index.html(template)을 참고하여 webpack에서 생성할 수 있도록 도와줌

 

  1. CleanWebpackPlugin
  • 이전 빌드 결과물을 삭제해주는 third party 플러그인

 

  1. MiniCssExtractPlugin
  • bundle된 JS코드 내부에 string으로 들어간 CSS코드를 추출해 별도의 파일로 분리해주는 third party 플러그인
  • JS 내부에 삽입되는 CSS 스타일 시트의 크기가 큰 경우 불러오는 데 오래 걸릴 수 있기에 분리해주는 것이 좋다
  • 배포시 사용하면 유용한 플러그인이다.

예시

/* webpack.config.js */
{
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            /* prod phase에서만 MiniCssExtractPlugin.loader 적용 */
            process.env.NODE_ENV === "production"
              ? MiniCssExtractPlugin.loader
              : "style-loader",
            "css-loader",
          ],
        },
      ]
    },
    plugins: [
        // prod phase에서만 css파일을 분리해서 js에 적용하도록 설정
        ...(process.env.NODE_ENV === 'production' ? [new MiniCssExtractPlugin({filename: '[name].css'})] : [])
    ]
}

tip

  • resolve는 절대경로, join은 상대경로를 나타낸다.
  • path: path.resolve(__dirname, 'dist') path: path.join(\_\_dirname, 'dist')

'REACT' 카테고리의 다른 글

리액트 훅  (0) 2022.05.30
PostCSS  (0) 2022.04.10
npx란??  (0) 2022.03.30
State and Lifecycle  (0) 2022.03.28
webpack 정리  (0) 2022.03.17