TIL | Webpack Basics

realryankim·어제
0

React

목록 보기
11/11
post-thumbnail

Webpack?

Webpack은 '자바스크립트 모듈 번들러(JavaScript Module Bundler)'다. 모듈은 프로그램을 구성하는 독립적인 요소로서 파일 단위로 구분된 것이라고 보면 되고, 번들러는 여러 개의 파일을 하나의 파일로 만들어주는 라이브러리다. 대표적인 예로 Parcel, Webpack 등이 있다.

Webpack에서 모든 것은 모듈이다. HTML, CSS, JS, 이미지 등 모든 것들을 모듈로서 관리한다. Webpack의 주요 개념으로는 Entry, Output, Loader, Plugin가 있다.

Entry

위에 보이는 이미지처럼 JS가 로딩하는 모듈이 많아질수록 모듈 간의 의존성이 증가한다. 의존성 그래프의 시작점을 Webpack에서는 엔트리(Entry)라고 부른다. Webpack은 엔트리를 통해서 필요한 모듈을 로딩하고 하나의 파일로 묶어준다. 여러 개의 엔트리가 존재할 수 있다.

// webpack.config.js
module.exports = {
  entry: {
    main: "./src/main.js",
  },
}

우리가 사용하게 될 html에서 JS의 시작점은 src/main.js 코드다. entry 키에 시작점 경로를 지정한다.

Output

엔드리에 설정한 JS파일을 시작으로 의존되어있는 모듈을 하나로 묶는다. 번들된 결과물을 처리할 위치를 Output에 기록한다.

// webpack.config.js
module.exports = {
  output: {
    filename: "bundle.js",
    path: "./dist",
  },
}

dist 폴더의 bundle.js 파일로 결과를 저장하고, html에서는 번들링 된 이 파일을 로딩하게 할 것이다.

index.html
<body>
  <script src="./dist/bundle.js"></script>
</body>
  
// CRA에서 root 파일을 지정해준 느낌인데?
<div id="root"></div>

엔트리에 설정된 자바스크립트는 Utils.js 모듈을 사용한다.

// src/main.js
import Utils from "./Utils"
Utils.log("Hello webpack")

// src/utils.js
export default class Utils {
  static log(msg) {
    console.log("[LOC] " + msg)

Loader

Webpack은 JavaScript와 Json만 이해할 수 있다. 로더는 다른 type의 파일(img, font, stylesheet 등)을 웹팩이 이해할 수 있도록 변경해준다. 로더는 testuse키로 구성된 객체로 설정할 수 있다.

  • test에 로딩할 파일을 지정한다.
  • use에 적용할 로더를 설정한다.

babel-loader

ES6에서 ES5로 변환할 때 바벨을 사용할 수 있는데, test에 ES6로 작성한 JS 파일을 지정하고 use에 이를 변환할 바벨 로더를 설정한다.

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: "node_modules",
        use: {
          loader: "babel-loader",
          options: {
            presets: ["env"],
          },
        },
      },
    ],
  },
}

test에 JS 확장자를 갖는 파일을 정규표현식으로 지정했다. node-modules 폴더는 패키지 폴더이므로 제외하기 위해서 exclude에 설정한다. use에 로더를 설정하는데 babel-loader를 추가했다.

로더를 사용하기 위해서는 노드패키지로 제공하는 로더를 npm으로 추가해야 한다.
npm i --save-dev babel-loader babel-core babel-preset-env

css-loader, style-loader

Webpack은 모든 것을 모듈로 다루기 때문에 CSS 파일을 JS로 변환해서 로딩해야 한다. css-loader가 그런 역할을 하는 로더다. css-loader를 적용한 뒤 번들링하면 CSS 코드가 JS로 변환된 것을 확인할 수 있다.

// dist/bundle.js
// module
exports.push([module.i, "body {\n  background-color: green;\n}\n", ""])

이렇게 모듈로 변경된 stylesheet는 돔에 추가되어야만 브라우저가 해석할 수 있다. style-loader는 JS로 변경된 stylesheet를 동적으로 돔에 추가하는 로더다. 보통 CSS를 번들링하기 위해서는 css-loader, style-loader를 함께 사용한다.

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
}
// src/style.css
body {
  background-color: green;
}

Plugin

Loader는 모듈을 처리하지만, Plugin은 번들된 파일을 처리한다. Plugin은 번들된 파일을 난독화하거나 특정 텍스트를 추출하는 용도로 사용된다. 예를 들어서 bundle한 css 파일과 js파일을 각각 html 파일에 link 태그와 script태그로 추가해줘야하는데 HtmlWebpackPlugin은 이것을 자동화해준다.

UglifyJsPlugin

UglifyJsPlugin은 로더로 처리된 JS 결과물을 난독화 처리하는 플러그인이다. 플러그인을 사용할 떄는 Webpack 설정 객체의 plugins 배열에 추가한다.

const webpack = require("webpack")

module.exports = {
  plugins: [new webpack.optimize.UglifyJsPlugin()],
}

ExtraTextPlugin

CSS의 전처리기인 사스(SASS)를 사용하려면 기존의 CSS 파일을 사스 파일로 변경해서 코딩한 뒤에 Webpack에서는 sass-loader만 추가해주면 된다. 이 역시 bundle.js 파일에 포함될 것이다.

만약 사스 파일이 매우 커진다면 분리하는 것이 효율적인 수 있다. bundle.js 파일이 아니라 style.css 파일로 따로 번들링한다는 말이다. 이 때 사용하는 것이 extract-text-webpack-plugin이다.

사스로더를 적용하면 아래와 같다. 로더의 test 키에 scss를 확장자로 갖는 파일로 지정한 뒤 기존 로더에 sass-loader를 추가한다.

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: ["style-loader", "css-loader", "sass-loader"],
      },
    ],
  },
}

사스 파일을 사용할 main.js에서 로딩한다.

// src/main.js
import Utils from "./Utils"

require("./style.scss") // sass 로딩

Utils.log("Hello webpack")

이렇게 설정한 뒤 번들링을 하면 bundle.js 파일이 생성되고 사스에 설정한 코드는 이 파일에 함께 포함되어 있을 것이다.

이제 별도로 CSS로 분리하기 위해 extract-text-webpack-plugin을 사용해보겠다.

// webpack.config.js
const ExtractTextPlugin = require("extract-text-webpack-plugin")

module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: ["css-loader", "sass-loader"],
        }),
      },
    ],
  },
  plugins: [new ExtractTextPlugin("style.css")],
}

plugin 배열에 new ExtractTextPlugin('style.css') 객체를 추가했다. style.css로 번들링하겠다는 것을 의미한다.

UglifyJsPlugin과 다르게 로더 쪽에 설정을 추가했다. 기존 로더를 제거하고, ExtractTextPlugin이 제공하는 extract() 함수 로더를 지정했다. 설정을 완료한 후 Webpack을 실행하면 dist 폴더에 bundle.js와 style.css 파일이 생성되어 있다.

정리!

  • Webpack은 JS 모듈 번들러다.
  • 의존성 그래프에서 엔트리로 그래프의 시작점을 설정한다.
  • Webpack은 모든 자원을 모듈로 로딩한 후 아웃풋 묶어준다.
  • 로더로 각 모듈별로 바벨, 사스 변환 등을 처리한다.
  • 플로그인이 결과물을 받아 난독화, 텍스트 추출 등의 추가 작업을 한다.
profile
💻 BE BETTER THAN I WAS YESTERDAY ☕

0개의 댓글