[TIL] 리액트랑 웹팩이랑 놀아보자

ansmeer008·2022년 11월 24일
1

Today I learn

목록 보기
60/65
post-thumbnail

오늘은 어제 배운 웹팩, 번들링을 리액트 파일일 때 적용해보는 과제를 수행했다.
리액트로 번들링은 처음이라... 조금 헤맸지만, 그래도 하나하나 해보면서 어제보다 좀 더 웹팩의 기능에 대해서 이해하게 된 것 같다.

과제 해결 과정

리액트 앱을 새롭게 만들어서 번들링을 진행한 건 아니고, 과제에서 주어진 래퍼런스 코드를 git clone해서 사용했다. 근데 해당 래퍼런스 코드 내부에는 server 폴더 파일과 client 폴더 파일이 따로 나뉘어져 있어서, 그리고 리액트는 client에서 쓰였기 때문에 client 파일을 따로 꺼내서 사용하기로 했다.

이런 방식 때문에 이후 github pages를 사용할 때 조금 애를 먹긴 하지만... 아무튼 그렇게 시작하기로 했다.

🔥 기본적인 설정들 : 설치, entry, ouyput, module...

► webpack과 babel, 플러그인 설치


$ npm install -D webpack webpack-cli


$ npm install --save-dev @babel/core babel-loader @babel/preset-react @babel/preset-env
//브라우저에서 JavaScript는 읽을 수 있지만 JSX는 읽을 수 없다. 
//여태까지는 create-react-app에 포함되어 있는 babel이 jsx를 js로 변경해주어 번들링을 해주기 때문에 브라우저에서 내가 만든 React 애플리케이션을 볼 수 있었음. 
//(참고로 babel은 JSX를 JavaScript로 변경하여 entry에서 불러올 수 있게 만들어줬기 때문에 로더의 일종으로 볼 수 있다.)


$ npm install --save-dev html-webpack-plugin
//html-webpack-plugin은 번들링 과정 중 html 파일을 
//자신이 원하는 형태로 가공해 번들에 포함할 수 있게 돕는다.

$ npm i -D css-loader style-loader

► webpack.config.js 파일 만들고 내용 작성

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");


module.exports = {
  entry: "./src/index.js",
  output: {
    path: path.join(__dirname, "/dist"),
    filename: "app.bundle.js",
  },
  module: {
    rules: [
      {
        test: /\.js$/,//test에는 정규식만 들어갈 수 있다. 
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
        },//바벨 로더 사용할 거라고 알려주기 
      },
      {
        test: /.s?css$/,//정규식으로 써줌 (css 혹은 scss)
        use: ["css-loader"],
        exclude: /node_modules/,
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "public", "index.html"),
    }),
  ],
};

바벨 presets 설정을 위해 .barbelrc 파일 만들어주기

바벨을 사용할 것이라고 웹팩에 알려주는 건 웹팩의 config 파일에서 해주었지만,
바벨 자체를 어떻게 설정할 것인지는 바벨의 설정 파일에서 완료해주어야 한다.

//.babelrc 파일 
{
  "presets": ["@babel/env", "@babel/react"]
}



🔥 모드별로 config 파일을 두 가지로 나눠보자

웹팩의 모드가 정확히 어떤 기준으로 나뉘는지 궁금해서 공식문서를 읽어봤는데, 사실 차이점이 잘 이해가 되진 않았다.

이 페이지를 참고하니 production 모드와 development 모드가 압축이나 성능 최적화에 있어서의 차이이다~ 정도로 이해할 수 있었다.

각 실행 모드에 따라 웹팩의 결과물 모습이 달라집니다. 개발 모드인 경우에는 개발자들이 좀 더 보기 편하게 웹팩 로그나 결과물이 보여지고, 배포 모드인 경우에는 성능 최적화를 위해 기본적인 파일 압축 등의 빌드 과정이 추가됩니다.

모드에 따라 if문이나 삼항연산자를 사용해서 어떤 플러그인이 설정되거나, 설정되지 않게도 설정할 수 있었지만, 과제에서 config 파일을 나누어보라고 했기 때문에 두 개의 파일로 나눠보기로 했다. (모드 옵션만 다르게 적어주고 대부분의 코드는 Production 모드 config 파일이든, development 모드 파일이든 동일하게 작성해주었다.)

//webpackDev.config.js

module.exports = {
  mode : "development"
  ...
}


//webpackPro.config.js 
module.exports = {
  //기본값이 production 모드라 생략해도 됨. 
}

모드는 문자열로 작성해주어야 한다. 처음에 아마 중괄호 안에 써줬던 것 같은데, 자꾸 에러가 떠서 뭐가 문제인지 찾아내는 데 시간이 좀 걸렸다..^^.....눈을 크게 뜨자...




🔥 번들링 할 때마다 dist 폴더가 정리되도록 해보자

output: {
   ...
    clean: true,
  },



🔥 아웃풋으로 나오는 파일의 이름이 매번 바뀌도록 해보자

 output: {
    ...
    filename: "[name].js",
   ...
  },



🔥 asset 관리를 해보자 : CSS에 minify 적용!

► mini-css-extract-plugin, css-minimizer-webpack-plugin 설치

❓mini-css-extract-plugin
mini-css-extract-plugin은 번들링을 할 때 css 파일을 따로 만들어주는 플러그인이다.
해당 플러그인이 없이 번들링을 하게되면 css 파일은 css-loader를 사용해 Js 파일 내에서 불러와서, style-loader를 통해 불러온 css를 style 요소 내에 담아주게 된다.

어제 공부하면서 style-loader와 MiniCssExtractPlugin.loader를 함께 사용하면 안됩니다!라는 문장을 본 적이 있는데, 지금보니 두 로더가 충돌하기 때문이라는 걸 알 수 있었다.

사실 최적화 과정이 파일을 하나 더 만드는 거라는 게 이해가 안 되기도 했는데,
파일을 합치는 게 따로 빼놓는 거 보다 나은 거 아닌가..? 했기 때문이다.
스터디원과 이야기해본 바로는 "스타일 요소를 dom 생성을 통해 만들어주는 게 css-loader인데,
그렇게 되면 자바스크립트 자체 처리량이 많아지니 오히려 css 파일로 빼는 게 최적화가 될 수도 있을 것 같다."라고 이야기하셔서 수긍했다.

❓css-minimizer-webpack-plugin
이 플러그인은 만들어진 css 파일을 최적화, 압축 해준다.
깃허브 문서를 참고해봅시다

npm install --save-dev mini-css-extract-plugin

npm install css-minimizer-webpack-plugin --save-dev

► webpack.cinfig.js 파일에 옵션 지정해주기

module.exports = {
  entry: "./src/index.js",
  output: {
    path: path.join(__dirname, "docs"),
    filename: "[name].js",
    clean: true,
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
        },
      },
      {
        test: /.s?css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],//추가 
        exclude: /node_modules/,
      },
    ],
  },
  optimization: {
    minimizer: [new CssMinimizerPlugin()],//최적화 옵션으로 추가해준다 
    runtimeChunk: "single",//entry 하나
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "public", "index.html"),
    }),
    new MiniCssExtractPlugin(),
  ],
  devServer: {
    static: "./dist",
  },
};



🔥 개발용 서버

webpack-dev-server는 간단한 웹 서버와 실시간 다시 로딩 기능을 제공한다고 한다.
공식문서

► 설치

$ npm install --save-dev webpack-dev-server

► config 파일에 server 옵션 추가해주기

module.exports = {
devServer: {
    static: "./dist",
  },
  optimization: {
    runtimeChunk: 'single',
  },
}

최적화 옵션에 runtimeChunk를 써주는 건 이 서버 옵션과 관련이 있는 것 같았는데 위에서도 첨부한 공식 문서에서는 아래와 같이 소개하고 있다.

optimization.runtimeChunk: 'single'이 추가된 이유(기본값은 multiple)는 이 예제에서 단일 HTML 페이지에 하나 이상의 엔트리 포인트가 있기 때문입니다. 이것이 없으면 여기에 설명된 문제가 발생할 수 있습니다. 자세한 내용은 코드 스플리팅 내용을 참고하세요.

► package.json 파일에서 scripts 수정해주기

config 파일을 둘로 나눴기 때문에 start를 했을 때 어떤 config 파일을 기반으로 서버를 시작할지를 따로 적어줬다.

build도 production 모드로 번들링 하고 싶을 때와 dev모드로 번들링 하고 싶을 때를 따로 나누어서 적어주었는데...

아무렴...🫠 이거보다 더 좋은 방법이 있을 거 같긴 한데 오늘 페어랑 머리 맞대고 고민한 결과물이라 그대로 올려본다.

	"scripts": {
	"start": "webpack-dev-server --config webpackDev.config.js --open --hot",
    "build": "webpack --mode production",
    "builddev": "webpack --config webpackDev.config.js",
      ...
    }



🔥 github pages로 배포해보자

이 분 블로그를 참고해서 대부분의 과정을 진행했다.

github pages는 공부해보면서 이해하기로는 깃헙에서 서버를 빌려주어서 내가 만든 프로젝트를 다른 사람들도 볼 수 있도록 해주는 서비스라고 이해했다. 즉 호스팅 서비스라고 할 수 있겠다.

나는 위 블로그를 참고해서 진행했기 때문에 gh-pages를 npm으로 설치해서 진행했지만

스터디원이 알려준 바로는 output path 속 폴더를 작성할 때 dist가 아니라 docs로 설정해주고, 깃허브 페이지 설정에서 root 폴더 말고 docs 폴더 옵션으로 설정해주면 gh-pages를 사용하지 않고도 깃허브 페이지를 발행할 수 있다고 한다.

profile
예술적인 코드를 짜는 프론트 엔드 개발자가 꿈입니다! (나는야 코드 아티스트! 🤭)

0개의 댓글