본문으로 바로가기

webpack.config.js는 다음과 같이 구성되어 있습니다.

 

하나씩 톺아봅시다.

const path = require("path");

const config = {
  mode: "none",
  entry: path.resolve(__dirname, "assets", "js", "main.js"),
  module: {
    rules: [
      {rule1},
      {rule2},
       {
        test: /\.(scss)$/,
        use: ExtractCSS.extract([
          {
            loader: "css-loader",
          },
          {
            loader: "postcss-loader",
            options: {
              plugin() {
                return [autoprefixer({ browsers: "cover 99.5%" })];
              },
            },
          },
          {
            loader: "sass-loader",
          },
        ]),
      }
    ],
  },
  output: {
    path:  path.join(__dirname, "static"),
    filename: "[name].[format]",
  },
};

module.exports = config;

 

 

mode

 

웹패 v4 부터 생긴 기능입니다.

  • none : 모드 설정 안함
  • development : 개발 모드
  • production : 배포 모드

node_env 환경 변수를 체크해서 모드를 바꿔주면 되겠죠? 

아니면 스크립트 단에서 다음과 같이 명령어를 날려줘도 됩니다.

webpack --mode=development

 

배포 모드일 때 조금 더 빌드가 빡세게(?) 된다고는 하는데 그렇다고 none으로 하면 번들링이 안되는 것도 아닙니다. 배포 단계에서만 신경 쓰면 됩니다.

 

 

entry

 

entry는 웹팩이 번들링을 시도하는 진입점입니다. 진입점을 설정하는 것이 중요한 이유는 entry를 기점으로 import 된 모듈들을 찾아서 번들링하기 때문입니다. 

CRA를 eject해서 entry가 어디인지 살펴보도록하겠습니다.

 

entry: [
  // isEnvDevelopment는 webpackEnv를 dev냐 prod냐를 체크합니다.
  isEnvDevelopment && require.resolve('react-dev-utils/webpackHotDevClient'),
  paths.appIndexJs,
].filter(Boolean),

웹팩 환경이 개발이냐 프로덕션이냐를 따져서 entry를 설정하는 군요

[].filter(Boolean)은 다음과 같이 작동합니다.

[1, 3, "", false].filter(Boolean) // output [1, 3]

 

참고로 entry는 반드시 한 개일 필요는 없습니다. 멀티 페이지 어플리케이션에서는 여러 개의 엔트리 포인트를 줄 수 있습니다.

entry: {
  login: './src/LoginView.js',
  main: './src/MainView.js'
}

 

 

output

 

번들링한 결과물을 어디 경로에 놓을 것인지를 결정합니다.

파일이름과 path를 정해놓으면 그곳에 정의해둡니다.

output: {
  path: path.join(__dirname, "static"),
  filename: "[name].js",
},

 

filename에는 여러 옵션을 넣어줄 수 있습니다.

 

// 결과 파일 이름에 entry 속성을 포함하는 옵션
filename: "[name].js", // main.js

// 웹팩 내부에서 부여하는 id (0, 1, 2...)
filename: "[id].js", // 0.js

// 웹팩 내부에서 부여하는 해시값
filename: "[hash].js", // 4d4b66c6905bd02ef198.js

// 모듈 내용을 기준으로 생생된 해시 값을 붙이는 옵션 (그냥 해쉬죠 뭐...)
filename: "[chunkhash].js", // 609f69712b6a1a422a1f.js

// 짬뽕하기
filename: "[name].[id].[hash].js",

 

CRA의 output은 어떨까요? 아, 꽤나 복잡하네요

output: {
  path: isEnvProduction ? paths.appBuild : undefined,
  pathinfo: isEnvDevelopment,
  filename: isEnvProduction ? 'static/js/[name].[contenthash:8].js' : isEnvDevelopment && 'static/js/bundle.js',
  futureEmitAssets: true,
  chunkFilename: isEnvProduction ? 'static/js/[name].[contenthash:8].chunk.js' : isEnvDevelopment && 'static/js/[name].chunk.js',
  publicPath: paths.publicUrlOrPath,
  devtoolModuleFilenameTemplate: isEnvProduction
    ? info =>
        path
          .relative(paths.appSrc, info.absoluteResourcePath)
          .replace(/\\/g, '/')
    : isEnvDevelopment &&
      (info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
  jsonpFunction: `webpackJsonp${appPackageJson.name}`,
  globalObject: 'this',
},

 

 

 

loader

 

앞서 작성한 엔트리 포인트에 css를 살포시 얹어보겠습니다. css 내용은 중요하지 않습니다.

import "./style.css";

function component() {
  const newDiv = document.createElement("div");

  newDiv.innerHTML = "hello guys";

  return newDiv;
}

document.body.appendChild(component());

 

이제 빌드를 시도해보면, 

 

ERROR in ./src/style.css 1:4

Module parse failed: Unexpected token (1:4)

You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. 

 

그러니까 css를 처리하는 적절한 로더가 없다는 것입니다.

 

css를 처리하는 로더는 "css-loader"입니다. 웹팩 홈페이지에서 찾아볼 수 있습니다.

(https://webpack.js.org/loaders/css-loader/)

 

말하는 대로 고분고분 설치해줍시다.

npm i css-loader -D

 

다음과 같이 webpack.config.js를 구성해주면됩니다. 

test는 적용할 파일의 유형, use는 적용할 로더입니다.

test에는 정규식이 사용됩니다. /\.css$/ 의 의미를 뜯어보면 //는 정규식 이란 의미이며 \.는 .이 특별한 의미가 아닌 일반 문자인 .을 의미한다는 것이며 css$는 css로 끝나는 것을 의미합니다.

const path = require("path");

module.exports = {
  mode: "none",
  entry: "./src/index.js",
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["css-loader"],
      },
    ],
  },
  output: {
    filename: "[name].js",
    path: path.resolve("dist"),
  },
};

 

로더에 대한 내용은 https://webpack.js.org/loaders/ 여기서 참고해보시면 될 것 같습니다.

 

아, 중요한 사실을 하나 빼먹었는데, css의 경우 js와 코드를 분리해줘야 합니다. 

mini-css-extract-plugin를 사용하시면 됩니다.

https://github.com/webpack-contrib/mini-css-extract-plugin

 

const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  mode: "none",
  plugins: [new MiniCssExtractPlugin()],
  entry: "./index.js",
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          { loader: MiniCssExtractPlugin.loader },
          { loader: "css-loader" },
        ],
      },
    ],
  },
  output: {
    filename: "[name].js",
    path: path.resolve("dist"),
  },
};

 

 

일반적으로 scss는 sass-loade, postcss-loader, css-loader 순으로 로더를 적용합니다.

(로더는 일반 코드와는 반대로 아래부터 적용됩니다!)

test: /\.scss$/,
use: [
 { loader: 'css-loader' },
 {
   loader: 'postcss-loader'
 },
 { loader: 'sass-loader' }
]

 

babel을 적용한 JS는 babel-loader면 뚝딱입니다.

{
  test: /\.js$/,
  use: [
    {
       loader: "babel-loader",
     },
  ],
},

 

 

이 것 외에도 사용되는 로더를 나열해보자면 다음과 같은 것이 있다고 합니다. 필요한 상황에 맞게 loader를 찾아보는 것이 중요하겠습니다.

 

 

plugin

 

로더가 코드를 변환한다면 플러그인은 번들링된 결과물을 변환한다고 보시면 되겠습니다.

간단히 웹팩에 내장된 ProgressPlugin 플러그인을 사용해보겠습니다. 웹팩의 빌드 진행을 프로그레시브하게 알려주는 플러그인입니다.

 

const path = require("path");
const webpack = require("webpack");

module.exports = {
  mode: "none",
  
  // 플러그인을 살포시 추가!
  plugins: [
    new webpack.ProgressPlugin((percentage, message, ...args) => {
      console.info(percentage, message, ...args);
    }),
  ],
  
  entry: "./src/index.js",
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["css-loader"],
      },
    ],
  },
  output: {
    filename: "[name].js",
    path: path.resolve("dist"),
  },
};

 

출력 결과의 일부를 가져와보면 다음과 같습니다. 

0 compiling
0.1 building 0/0 modules 0 active 
0.1 building 0/1 modules 1 active C:\Users\BOSSMONSTER\Documents\webpacktest\src\index.js
0.10120000000000001 building 1/1 modules 0 active 
0.10120000000000001 building 1/2 modules 1 active C:\Users\BOSSMONSTER\Documents\webpacktest\node_modules\css-loader\dist\cjs.js!C:\Users\BOSSMONSTER\Documents\webpacktest\src\

 

각종 플러그인들은 웹팩 공식 문서를 참고하시거나, github을 뒤져보시면 될 것 같습니다.

https://webpack.js.org/plugins/

 

 

 

사실 이 특성 외에도 resolve, DevServer, devtool이 존재합니다만, 기본적인 웹팩 사용은 이 정도로 이루어져 있습니다.

 

 


기본적으로 다음과 같은 loader가 있다고 webpack 홈페이지에 써있습니다.

webpack.js.org/loaders/

 

Files

  • raw-loader Loads raw content of a file (utf-8)
  • val-loader Executes code as module and consider exports as JS code
  • url-loader Works like the file loader, but can return a data URL if the file is smaller than a limit
  • file-loader Emits the file into the output folder and returns the (relative) URL
  • ref-loader Create dependencies between any files manually

JSON

Transpiling

Templating

Styling

Linting && Testing

Frameworks

Awesome

For more third-party loaders, see the list from awesome-webpack.


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체