프론트엔드 개발 환경 공부 #8 자주 사용하는 플러그인

Jake Seo·2021년 9월 18일
0

자주 이용되는 플러그인

사실 이전시간에 플러그인을 간단히 만들어보았지만, 일반적인 업무에서 플러그인을 만들 일은 잘 없다. 다만, 자주 사용하는 플러그인을 학습할 필요는 있다. 로더처럼 플러그인도 자주 사용되는 것들이 있다.

웹팩에서 직접 제공하는 플러그인을 사용하거나 써드파티 라이브러리를 찾아 자주 사용하는 플러그인에 대해 알아보자.

BannerPlugin

빌드한 결과물에 빌드 정보나 커밋 버전 등을 추가하는데 이용되는 플러그인이다.

적용해보기

webpack.config.js

const webpack = require("webpack");

module.exports = {
    ...
    plugins: [
        new webpack.BannerPlugin({ banner: `배너 테스트, 빌드 시간: ${new Date().toLocaleDateString()}` }),
    ]
};

위와 같이 추가하면 사용할 수 있다. 공식문서를 보면 다양한 옵션과 용례가 있다.

결과 살펴보기

내가 추가한 문자가 잘 들어있다.

배너 예쁘게 꾸며보기

const webpack = require("webpack");
const childProcess = require("child_process");

module.exports = {
    ...
    plugins: [
        new webpack.BannerPlugin({
            banner: `
            name: [name] 
            content: 배너 테스트 
            date: ${new Date().toLocaleDateString()}
            commit version: ${childProcess.execSync(
                "git rev-parse --short HEAD"
            )}
            author: ${childProcess.execSync("git config user.name")} 
            `,
        }),
    ],
};

위와 같이 예쁘게 꾸며보았다.

Nodejs의 내장 모듈인 child_process 모듈은 명령프롬프트에서 명령어 실행 결과로 반환받는 문자열을 그대로 가져올 수 있다.

배너를 사용하는 이유

  1. 버전이 바뀌어 올바르게 배포 되었는지 확인
  2. 모든 파일이 잘 빌드되었는지 확인

보통 이러한 이유로 쓴다.

DefinePlugin

현업에서 애플리케이션을 개발하다보면, 보통 3가지 환경으로 나눈다. 로컬, 개발, 운영 이 과정에서 환경에 따라 API 서버 주소가 다를 수 있다. 소스 코드를 다른 환경에서 실행시킬 때, 소스코드를 직접 매번 일일이 바꾸는 것은 비효율적이며 실수하기 쉽다.

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

공식문서 설명

공식문서 링크

DefinePlugin은 컴파일 타임에 코드에 있는 변수를 다른 값이나 표현식으로 변경해준다. 이러한 기능은 개발 빌드와 프로덕션 빌드 사이에서 다른 동작을 주어야할 때 유용하다. 개발 빌드에서 로깅을 수행하지만, 프로덕션 빌드에서는 수행하고 싶지 않다면, 전역 상수를 사용하여 로깅이 일어날지를 결정할 수 있다. 일단 설정해놓고 개발 및 프로덕션 환경을 잊어버리면 된다.

용례

DefinePlugin으로 넘어온 각각의 키가 .으로 조인된 단일 혹은 다수의 식별자이다.

  • 값이 문자열이라면, 코드 fragment로 사용된다.
  • 값이 문자열이 아니라면, (함수와 함께) stringified 된다.
  • 값이 오브젝트라면, 모든 키가 같은 방식으로 정의된다.
  • 키 앞에 typeof prefix를 붙이면, typeof 호출에 대해서만 정의된다.

값은 인라인화되어 코드에 들어갈 것이며, 중복 조건 제거를 위해 최소화 단계를 거친다.

적용해보기

// node.js의 CommonJS 를 사용한 모듈화
const path = require("path");
const HelloWorldPlugin = require("./custom-plugin");
const webpack = require("webpack");
const childProcess = require("child_process");

module.exports = {
    ...
    plugins: [
        new webpack.DefinePlugin({
            DEFINE_PLUGIN_TEST: "1+1",
        }),
    ],
};

위와 같이 적용하면 어떻게 될까? 값이 문자열이라서 코드 fragment로 사용될 것이다. 그 말인 즉슨, 문자열 자체로 평가되는 게 아니라 코드로 변환돼서 평가된다는 것이다. 즉 그냥 1+1 문자열이 나오는 것이 아니라 그 결과인 2가 나온다는 뜻이다.

그리고 process.env.NODE_ENV에는 우리가 웹팩에서 설정한 개발단계 정보가 들어가있는 것을 확인할 수 있다.

문자열 적용해보기

const path = require("path");
const HelloWorldPlugin = require("./custom-plugin");
const webpack = require("webpack");
const childProcess = require("child_process");

module.exports = {
    ...
    plugins: [
        new webpack.DefinePlugin({
            DEFINE_PLUGIN_TEST: "1+1",
            DEFINE_PLUGIN_STRING: JSON.stringify("1+1"),
        }),
    ],
};

문자열로 넣고 싶을 때는 JSON.stringify()를 이용할 수 있다.

HtmlTemplatePlugin

HtmlTemplatePlugin은 HTML 파일을 후처리하는데 사용하며, 빌드 타임의 값을 넣거나 코드를 압축할 수 있다.

이 플러그인은 웹팩의 기본 플러그인은 아니고, 서드파티 패키지이기 때문에 따로 설치를 해주어야 한다.

패키지 다운로드

npm install -D html-webpack-plugin

웹팩에 플러그인 적용해보기

// node.js의 CommonJS 를 사용한 모듈화
const path = require("path");
const HelloWorldPlugin = require("./custom-plugin");
const webpack = require("webpack");
const childProcess = require("child_process");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    ...
    plugins: [
        ...
        new HtmlWebpackPlugin({
            template: "./index.html",
        }),
    ],
};

이번에는 webpack.에서 불러오는 게 아니라, require("html-webpack-plugin") 코드로 패키지를 불러온 뒤에 new 키워드로 해당 오브젝트를 생성했다.

index.html에서 js 불러오는 부분 지우기

<script src="./dist/main.js"></script> 부분을 지웠다.

빌드하고 결과보기

결과가 잘 나온다.

<script> 부분을 지웠었는데, HtmlWebpackPlugin에 의해 다시 생겼다.

HtmlWebpackTemplate의 기능

  • 조금 더 템플릿을 동적으로 만들 수 있다.
    • <script> 태그도 직접 안넣었지만, 자동으로 들어가 있다. 나중에 결과물의 이름이 바뀌어도 경로가 잘 변경되어 들어갈 것이다.
    • ejs라는 문법을 활용하여 HTML에 변수를 넣어줄 수 있다.

EJS를 이용하여 변수 넣어보기

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>테스트용2 <%=env%></title>
    </head>
    <body>
        <span class="text-blue">콘솔을 확인해봅시다222</span>
    </body>
</html>

<%=env%>로 변수 값을 가져올 수 있다.

const path = require("path");
const HelloWorldPlugin = require("./custom-plugin");
const webpack = require("webpack");
const childProcess = require("child_process");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    ...
    plugins: [
        ...
        new HtmlWebpackPlugin({
            template: "./index.html",
            templateParameters: {
                env:
                    process.env.NODE_ENV === "development"
                        ? "(개발용)"
                        : "(프로덕션용)",
            },
        }),
    ],
};

위와 같이 작성하면, process.env.NODE_ENV의 값에 따라서 다른 결과가 나오게 할 수 있다.

EJS 이용 결과

NODE_ENV=development npm run build

위와 같이 명령어를 치면

개발용으로 잘 나오고,

NODE_ENV=production npm run build

위와 같이 입력하면,

프로덕선용으로 잘 나온다.

minify 기능 사용해보기

const path = require("path");
const HelloWorldPlugin = require("./custom-plugin");
const webpack = require("webpack");
const childProcess = require("child_process");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    ...
    plugins: [
        ...
        new HtmlWebpackPlugin({
            template: "./index.html",
            templateParameters: {
                env:
                    process.env.NODE_ENV === "development"
                        ? "(개발용)"
                        : "(프로덕션용)",
            },
            minify: {
                collapseWhitespace: true,
                removeComments: true,
            },
        }),
    ],
};

위와 같이 minify를 이용하면, html 파일의 크기를 최소화할 수 있다.

한줄로 코드가 입력되었고, 주석이 제거되었다.

실제 환경에서는

            minify:
                process.env.NODE_ENV === "production"
                    ? {
                          collapseWhitespace: true,
                          removeComments: true,
                      }
                    : false,

위와 같이 프로덕션 환경에서만 작동하게 하고, 아니면 false값을 주는 것이 좋다.

CleanWebpackPlugin

이 플러그인은 빌드 이전의 결과물을 제거하는 플러그인이다. 이 플러그인이 없으면 과거에 사용했던 아웃풋이 전부 남아있다. 빌드 내용이 덮어씌워지면 상관은 없지만, 파일의 이름이 변경되는 등 많은 이유로 찌꺼기가 남을 수 있으니, 이 플러그인을 이용해서 매번 빌드 때마다 깔끔하게 제거해주는 것이 좋다.

패키지 설치하기

npm install -D clean-webpack-plugin

웹팩에 설정 추가하기

const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
    plugins: [
        new CleanWebpackPlugin(),
    ],
};

추가하는 방법이 매우 간단한데, 딱 한가지 주의할 점은 require할 때, {}로 구조분해 할당을 이용해서 들고와야 한다는 것이다. defaultexport하지 않았기 때문이다.

MiniCssExtractPlugin

이전에 보았듯, 웹팩을 이용해서 CSS를 번들링된 JS 형태로 만들었다. 하지만, CSS가 점점 많아지면, 번들링되는 JS도 크기가 점점 증가할 수 있다. 그러면 단일로 너무 큰 파일을 받아와야 해서 페이지 로딩 속도가 느려질 수 있다.

브라우저 환경에서는 큰 파일 하나를 내려받는 것보다 작은 파일 여러개를 동시에 내려받는 것이 더 빠르다.

개발 환경에서는 CSS를 하나의 모듈로 처리해도 상관없지만, 프로덕션 환경에서는 분리해주는 것이 효과적이다. MiniCssExtractPlugin은 CSS 별로 하나의 파일로 뽑아내는 플러그인이다.

웹팩에 설정 추가하기

// node.js의 CommonJS 를 사용한 모듈화
const path = require("path");
const HelloWorldPlugin = require("./custom-plugin");
const webpack = require("webpack");
const childProcess = require("child_process");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    process.env.NODE_ENV === "production" ?
                    MiniCssExtractPlugin.loader :
                    // 로더의 실행 순서는 뒤에서부터 앞이다.
                    "style-loader",
                    "css-loader",
                ],
            },
            ...
        ],
    },
    ...
    plugins: [
        ...,
        ...(process.env.NODE_ENV === "production"
            ? [new MiniCssExtractPlugin({ filename: "[name].css" })]
            : []),
    ],
};

위와 같이 설정해주면 된다. 일반적으로 프로덕션 환경에서만 쓰기 때문에 use에 프로덕션 환경에서만 쓰도록 코딩을 해주었다.

style-loaderMiniCssExtractPlugin.loader로 바꿔주면 된다. css-loader는 두 로더중 어느 것을 사용해도 여전히 필요하다.

전개 연산자(spread operator)를 통해서 production일 때만, MiniCssExtractPlugin을 로드하도록 설정했다. 전개 연산자에서는 [...[]]를 입력하면 []가 되며, [...[a, b]]을 입력하면, [a, b]가 된다.

결과

main.css 파일이 생겼으며, index.html에서도 main.css 파일을 불러오는 부분이 생겼다.

profile
풀스택 웹개발자로 일하고 있는 Jake Seo입니다. 주로 Jake Seo라는 닉네임을 많이 씁니다. 프론트엔드: Javascript, React 백엔드: Spring Framework에 관심이 있습니다.

0개의 댓글