TIL 69 | Webpack Basics

meow·2020년 10월 18일
1

React

목록 보기
25/33
post-thumbnail

리액트를 공부하면서 항상 CRA를 사용해서 초기 개발 환경을 구축했는데, 다음주부터 나가는 기업협업에서는 웹팩을 사용한다는 이야기를 선배 기수에게 들었다. 미리 웹팩을 훑고 가면 좋다는 조언을 듣고, 여러 블로그와 유튜브를 찾아보며 웹팩을 이해해보고 있다!

참고 자료
리액트 웹팩으로 개발 환경 구축하기(without CRA)
웹팩의 기본 개념

웹팩?

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

웹팩에서 모든 것은 모듈이다. HTML, 자바스크립트, CSS, 이미지 등 모든 것을 모듈로서 관리한다. 웹팩의 주요 개념으로는 Entry, Output, Loader, Plugin이 있다.

Entry

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

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

우리가 사용할 html에서 자바스크립트의 시작점은 src/main.js코드이다. entry 키에 시작점 경로를 지정한다.

Output

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

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

dist 폴더의 bundle.js 파일로 결과를 저장할 것이다. html에서는 번들링 된 이 파일을 로딩하게 한다. (오! 마치 CRA에서 root 파일을 지정해준 느낌이다! <div id="root"></div>)

index.html
<body>
  <script src="./dist/bundle.js"></script>
</body>

엔트리에 설정된 자바스크립트는 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("[LOG] " + msg)
  }
}

Loader

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

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

babel-loader

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

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

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

로더를 사용하기 위해서는 노드패키지로 제공하는 로더를 npm으로 추가해야 한다.

npm i --save-dev babel-loader babel-core babel-preset-env

css-loader, style-loader

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

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

이렇게 모듈로 변경된 스타일시트는 돔에 추가되어야만 브라우저가 해석할 수 있다. style-loader는 자바스크립트로 변경된 스타일시트를 동적으로 돔에 추가하는 로더이다. 보통 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;
}

추가 자료 : Loader란? 어떻게 써야 할까?

Plugin

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

UglifyJsPlugin

UglifyJsPlugin은 로더로 처리된 자바스크립트 결과물을 난독화 처리하는 플러그인이다. 플러그인을 사용할때는 웹팩 설정 객체의 plugins 배열에 추가한다.

const webpack = require("webpack")

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

ExtractTextPlugin

CSS의 전처리기인 사스(SASS)를 사용하려면 기존의 CSS 파일을 사스 파일로 변경해서 코딩한 뒤 웹팩에서는 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() 함수 로더를 지정했다. 설정을 완료한 후 웹팩을 실행하면 dist 폴더에 bundle.js와 style.css 파일이 생성되어 있다.

정리해보기!

  • 웹팩은 자바스크립트 모듈 번들러이다.
  • 의존성 그래프에서 엔트리로 그래프의 시작점을 설정한다.
  • 웹팩은 모든 자원을 모듈로 로딩한 후 아웃풋으로 묶어준다.
  • 로더로 각 모듈별로 바벨, 사스 변환 등을 처리한다.
  • 플러그인이 결과물을 받아 난독화, 텍스트 추출 등의 추가 작업을 한다.
profile
🌙`、、`ヽ`ヽ`、、ヽヽ、`、ヽ`ヽ`ヽヽ` ヽ`、`ヽ`、ヽ``、ヽ`ヽ`、ヽヽ`ヽ、ヽ `ヽ、ヽヽ`ヽ`、``ヽ`ヽ、ヽ、ヽ`ヽ`ヽ 、ヽ`ヽ`ヽ、ヽ、ヽ`ヽ`ヽ 、ヽ、ヽ、ヽ``、ヽ`、ヽヽ 🚶‍♀ ヽ``ヽ``、ヽ`、

2개의 댓글

comment-user-thumbnail
2020년 10월 18일

이번에 처음으로 웹팩을 배우게 됐는데, 매 번 도움이 되는 글을 올려주시는 거 같아요! 잘 배우고 갑니다 ^^

1개의 답글