React 33장 - 번들링과 웹팩 (2)
포스트
취소

React 33장 - 번들링과 웹팩 (2)

React

웹팩

튜토리얼 1

디렉터리 생성

1
2
3
cd ~/Dekstop
mkdir Webpack-practice
cd Webpack-practice

npm init

1
npm init -y
  • 현재 디렉터리에 package.json 파일을 생성해준다.
1
2
3
4
5
6
7
8
9
10
11
{
    "name": "Webpack-practice",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "test": "echo \"Error: no test specified\",&& exit 1"
    },
    "keywords": [],
    "author": "",
}

index.js 파일 생성

  • src/index.js 파일을 생성하고, 매개변수를 console.log하는 간단한 함수를 만든다.

    1
    
    const shout = (...sentences) => console.log(...sentences);
    
  • loadsh를 설치하기 전에, once를 직접 구현해본다.
  • src/underbar.js에 파일을 생성하고 코드를 작성한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    const _ = {
      once(func) {
        let result;
        let alreadyCalled = false;
    
        return function (...args) {
          if (!alreadyCalled) {
            alreadyCalled = true;
            result = func(...args);
          }
          return result;
        };
      },
    };
    
    module.exports = _;
    
  • src/index.js에서 _를 불러와서 사용한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    const _ = require('src/underbar.js');
    
    const shout - (...sentences) => console.log(...sentences);
    
    const loremIpsum = "Lorem ipsum dolor sit ...";
    
    const shoutOnce = _.once(shout);
    
    shoutOnce(loremIpsum);
    shoutOnce(loremIpsum);
    shoutOnce(loremIpsum);
    shoutOnce(loremIpsum);
    
  • node src/index.js로 파일을 사용해보면 Lorem ipsum이 한 번만 출력되는 것을 볼 수 있다.

웹팩 설치하기

1
npm install -D webpack webpack-cil
  • 웹팩을 사용하기 위해서 npm으로 webpack, webpack-cil를 설치해야 한다.
  • webpack은 번들링하기 위한 라이브러리이지만, 실제 프로젝트에 사용하지 않기 때문에 devDependency 옵션을 설정하고 설치한다.
  • 번들링을 원하는 파일의 위치를 entry, 번들링의 결과물을 output이라고 한다.

웹팩 config 파일 작성

  • webpack 설정 파일인 webpack.config.js를 생성하고 파일에 entry와 output 정보를 작성한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    const path = require("path");
    
    module.exports = {
      entry: "./src/index.js",
      output: {
        path: path.resolve(__dirname, "dist"), // ./dist의 절대 경로를 리턴한다.
        filename: "app.bundle.js",
      },
    };
    

번들링하기

  • 번들링 하기 위해서 해당 명령어를 입력한다.

    1
    
    npx webpack
    
  • dist/app.bundle.js 파일이 생성된다면 성공적이다. image

  • 번들링이 잘 되었다면 node dist/app.bundle.js를 통해 기존의 index.js의 결과가 나왔다면 성공적이다.

npm run build 설정하기

  • npm script를 새롭게 만든다면 npm run build 스크립트로 언제든 번들링할 수 있다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    {
        "name": "Webpack-practice",
        "version": "1.0.0",
        "description": "",
        "main": "index.js",
        "scripts": {
            "build": "webpack",
            "test": "echo \"Error: no test specified\",&& exit 1"
    },
        "keywords": [],
        "author": "",
        "devDependencies": {
            "webpack": "^5.73.0",
            "webpack-cil":"^4.10.0"
        }
    }
    

정리

  • entry 파일이 필요한 모든 것을 webpack이 모아서 번들링을 해준다.
  • 번들링의 결과물이 output 경로로 산출된다. image

  • entry 경로의 index.js파일이 필요한 디펜던시가 underbar.js밖에 없기 때문에 이런 경우는 번들링이 불필요하다.
  • 온전한 애플리케이션을 위해 필요한 라이브러리는 가면 갈수록 많아지기 때문에, 이를 잘 번들링할 수 있어야 한다. image

튜토리얼 2

  • CSS도 함께 작업하기 위해 src/index.html을 작성해본다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    <!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>Shout Lorem Ipsum</title>
      </head>
      <body>
        <div id="app"></div>
        <script src="index.js"></script>
      </body>
    </html>
    
  • src/index.html을 실행하면 오류가 발생하는데, require 문법은 Node.js문법으로 브라우저에서 지원하지 않기 때문이다.
  • 리액트를 설치하면 자연스럽게 import,export를 사용할 수 있는데, 리액트 또한 webpack을 사용하기 때문에 가능한 일이고 번들링 해준 것이다.
  • index.html파일을 dist 디렉터리로 옮겨서 번들 파일과 연결시킨다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    <!-- dist/index.html -->
    <!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>Shout Lorem Ipsum</title>
      </head>
      <body>
        <div id="app"></div>
        <script src="app.bundle.js"></script>
      </body>
    </html>
    
  • src/index.js에 코드를 추가한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    
    const _ = require("./underbar.js");
    
    const shout = (...sentences) => console.log(...sentences);
    const shoutToHTML = (...sentences) => {
      const app = document.querySelector("#app");
      app.append(
        ...sentences.map((sentence) => {
          const shoutHere = document.createElement("div");
          shoutHere.className = "shout";
          shoutHere.textContent = sentence;
          return shoutHere;
        })
      );
      return;
    };
    
    const loremIpsum =
      "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis egestas feugiat elit, ac tincidunt neque vestibulum at. Mauris a eros sit amet urna efficitur tempus.";
    
    const shoutOnce = _.once(shout);
    const shoutToHTMLOnce = _.once(shoutToHTML);
    
    shoutOnce(loremIpsum);
    shoutOnce(loremIpsum);
    shoutOnce(loremIpsum);
    shoutOnce(loremIpsum);
    
    shoutToHTMLOnce(loremIpsum);
    shoutToHTMLOnce(loremIpsum);
    shoutToHTMLOnce(loremIpsum);
    shoutToHTMLOnce(loremIpsum);
    
  • 작성한 코드는 app.bundle.js에 적용되지 않았기 때문에, 다시 npm run build로 번들링을 진행한다.
  • html 파일에 h1요소를 추가하고 CSS를 작성한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    * {
      box-sizing: border-box;
      border: 0;
      padding: 0;
      margin: 0;
    }
    
    main {
      display: flex;
      justify-content: center;
      align-items: center;
      flex-direction: column;
    }
    
    div.shout {
      padding: 12px;
      margin: 4px;
      border-radius: 8px;
      border: 0.5px solid gray;
    }
    
  • 작성한 CSS는 쉽게 배포할 수 있도록 loader를 제공한다.
  • create-react-app에서 CSS를 import할 수 있었던 이유는 webpack에서 CSS를 불러올 수 있는 툴을 사용하기 때문이다.
  • dist/style.css 파일의 위치를 src/style.css로 옮기고, 파일을 index.js에서 불러온다.
  • node src/index.js명령으로 확인하면 Node.js 자체만으로 CSS를 읽을 수 없어 문법 에러가 발생한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    
    const _ = require("./underbar.js");
    require("./style.css");
    
    const shout = (...sentences) => console.log(...sentences);
    const shoutToHTML = (...sentences) => {
      const app = document.querySelector("#app");
      app.append(
        ...sentences.map((sentence) => {
          const shoutHere = document.createElement("div");
          shoutHere.className = "shout";
          shoutHere.textContent = sentence;
          return shoutHere;
        })
      );
      return;
    };
    
    const loremIpsum =
      "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis egestas feugiat elit, ac tincidunt neque vestibulum at. Mauris a eros sit amet urna efficitur tempus.";
    
    const shoutOnce = _.once(shout);
    const shoutToHTMLOnce = _.once(shoutToHTML);
    
    shoutOnce(loremIpsum);
    shoutOnce(loremIpsum);
    shoutOnce(loremIpsum);
    shoutOnce(loremIpsum);
    
    shoutToHTMLOnce(loremIpsum);
    shoutToHTMLOnce(loremIpsum);
    shoutToHTMLOnce(loremIpsum);
    shoutToHTMLOnce(loremIpsum);
    

loader 설치

  • style-loader Add exports of a module as style to DOM
  • css-loader Loads CSS file with resolved imports and returns CSS code
  • less-loader Loads and compiles a LESS file
  • sass-loader Loads and compiles a SASS/SCSS file
  • postcss-loader Loads and transforms a CSS/SSS file using PostCSS
  • stylus-loader Loads and compiles a Stylus file
1
npm i -D css-loader style-loader
  • webpack.config.js를 작성한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    // webpack.config.js
    const path = require("path");
    
    module.exports = {
      entry: "./src/index.js",
      output: {
        path: path.resolve(__dirname, "dist"),
        filename: "app.bundle.js",
      },
      module: {
        rules: [
          {
            // 파일명이 .css로 끝나는 모든 파일에 적용
            test: /\.css$/,
            // 배열 마지막 요소부터 오른쪽에서 왼쪽 순으로 적용
            // 먼저 css-loader가 적용되고, styled-loader가 적용되어야 한다.
            // 순서 주의!
            use: ["style-loader", "css-loader"],
            // loader가 node_modules 안의 있는 내용도 처리하기 때문에
            // node_modules는 제외해야 합니다
            exclude: /node_modules/,
          },
        ],
      },
    };
    
  • 번들링이 성공적으로 되었다면 app.bundle.js파일을 열고 (alt+shift+F)를 사용하여 코드를 확인한다.
  • <link rel="stylesheet" href="style.css"> 코드는 없어도 된다.

정리

  • loader는 JavaScript,JSON이 아닌 파일을 불러오는 역할을 한다. image

튜토리얼 3

  • 따로 생성했던 dist/index.html을 src디렉터리로 옮기고 작업을 시작한다.

    • LICENSE
    • dist
      • app.bundle.js
    • package-lock.json
    • package.json
    • src
      • index.html
      • index.js
      • style.css
      • underbar.js
    • webpack.config.js
  • html-webpack-plugin을 설치한다.

    1
    
    npm i -D html-webpack-plugin
    
  • 설치 후 webpack.config.js파일에 해당 플러그인을 적용한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    const path = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    
    module.exports = {
      entry: "./src/index.js",
      output: {
        path: path.resolve(__dirname, "dist"),
        filename: "app.bundle.js",
      },
      module: {
        rules: [
          {
            test: /\.css$/,
            use: ["style-loader", "css-loader"],
            exclude: /node_modules/,
          },
        ],
      },
      plugins: [
        new HtmlWebpackPlugin({
          template: path.resolve(__dirname, "src", "index.html"),
        }),
      ],
    };
    

image

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.