cra 없이 webpack+babel로 리액트 초기 설정하기!

모야 프로젝트를 진행하면서 초기 세팅을 맡게되었다.

cra는 webpack과 babel 세부설정을 위해선 eject해야한다.

유지보수를 위해서 처음부터 cra없이 세팅하는게 맞다는 생각이 들어 직접 세팅하였다.

webpack은 공식문서가 잘 되어있어서 수월하게 세팅할 수 있었다.

아래의 세팅은 정답이 아니다..!

초기 설정

src 폴더와 public 폴더를 만들었다.
src 폴더에는 js 파일들이 작성된다.
public 폴더에는 index.html을 만들었는데, src의 js파일들을 webpack으로 번들링하여 하나의 js파일을 만든다. 그리고 이를 사용한다..!

먼저 초기설정을 해준다.
루트디렉토리로 가서 아래의 커맨드를 입력하면 된다.

1
2
3
4
5
npm init -y
mkdir src public
// src 폴더와 public 폴더를 만든다.
touch src/index.js public/index.html
// 진입점을 정의한다.

public/index.html은 다음과 같이 작성한다.
./bundle.js는 webpack으로 번들링된 결과물이다.

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>Document</title>
</head>
<body>
<div id="root"></div>
<script src="./bundle.js"></script>
</body>
</html>

index.js는 다음과 같이 작성한다.
App 컴포넌트의 리턴값은 진입점이라 생각하고 작성해주면 된다.

1
2
3
4
5
6
7
8
import React from "react";
import reactDOM from "react-dom";

const App = () => {
return <div>hi</div>;
};

reactDOM.render(<App />, document.getElementById("root"));

필요한 모듈 설치

필요한 모듈은 어떤 작업을 할지에 따라 달라진다.
나는 아래의 모듈들을 설치하였다.

1
2
3
4
5
6
7
8
9
10
11
12
npm i @babel/core @babel/preset-env @babel/preset-react babel-loader -D
// babel과 babel의 preset 그리고 webpack과 babel을 연결하기 위한 loader
npm i css-loader node-sass sass-loader style-loader -D
// css를 로드하기위해 설치
npm i "@pmmmwh/react-refresh-webpack-plugin" react-refresh -D
// react hot-reload를 위한
npm i webpack webpack-cli -D
// webpack
npm i webpack-dev-server
// 개발용 서버를 위한 webpack-dev-server 설치
npm i file-loader
// 정적 이미지를 가져오기위해 설치

바벨 세팅

루트 디렉토리에서 다음과 같은 커맨드를 입력한다.

1
touch .babelrc

preset는 자주 쓰이는 plugin들의 집합이다.

babel팀에서 공식적으로 제공하는 preset과 비공식 preset이 있다.

필수적인 preset을 입력하였다.

또한 plugin에는 핫 리로딩을 위해 react-refresh를 넣어주었다.

최종적으로 .babelrc의 내용은 다음과 같다.

1
2
3
4
{
"presets": ["@babel/preset-env", "@babel/preset-react"],
"plugins": ["react-refresh/babel"]
}

webpack.config.js 설정

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
const path = require("path");
// 절대경로를 위한 모듈을 import
const RefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
// 핫리로딩을 위한 플러그인
const webpack = require("webpack");
// 환경변수 설정을 위해 webpack을 불러옴

module.exports = {
mode: "development",
// 모드
entry: "./src/index.js",
//진입점이 될 파일
output: {
path: path.join(__dirname, "public"),
//경로
filename: "bundle.js",
//결과물의 이름
},
resolve: {
extensions: [".js", ".jsx", "json"],
alias: {
"@images": path.resolve(__dirname, "public/images"),
"@components": path.resolve(__dirname, "src/components"),
"@reducers": path.resolve(__dirname, "src/reducers"),
"@sagas": path.resolve(__dirname, "src/sagas"),
"@utils": path.resolve(__dirname, "src/utils"),
},
},
// 절대경로 설정
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: "babel-loader",
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.sass$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: "file-loader",
},
],
},
plugins: [
new RefreshWebpackPlugin(),
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("development"),
// 환경변수 설정
// https://yamoo9.gitbook.io/webpack/webpack/webpack-plugins/manage-env-variables
}),
],
devtool: "eval-cheap-module-source-map",
// 소스를 매핑하는 방법
// 여러가지 옵션이 있다..! https://webpack.kr/configuration/devtool/
devServer: {
static: {
directory: path.join(__dirname, "public"),
// 서버에 정적파일의 위치를 알려줌
},
port: 3000,
hot: true,
},
// https://webpack.js.org/configuration/dev-server/
};

eslint + prettier 설정하기

코드 컨벤션을 위해 eslint와 prettier를 적용하였다.
@babel/polyfill은 devDependencies가 아닌 dependencies로 설치해주어야 한다.

1
npm i eslint eslint-config-prettier eslint-plugin-prettier prettier -D

prettier파일을 다음과 같이 작성하였다.
옵션은 공식문서를 참조하였다.

1
2
3
4
5
6
7
8
9
10
11
12
{
"printWidth": 80,
"tabWidth": 2,
"singleQuote": false,
"trailingComma": "all",
"semi": true,
"useTabs": false,
"arrowParens": "always",
"endOfLine": "auto",
"bracketSpacing": true,
"jsxBracketSameLine": true
}

.eslintrc 파일을 다음과 같이 작성해주었다.

1
2
3
4
5
6
7
8
{
"plugins": ["prettier"],
"extends": ["eslint:recommended", "plugin:prettier/recommended"],
"parser": "babel-eslint",
"rules": {
"prettier/prettier": "error"
}
}

babel polyfill 설정하기

더 이상 사용되지 않는 모듈이라고 한다.

@babel/polyfill을 보면 core-js/stable과 regenerator-runtime/runtime로 대체하여 사용한다고 한다!

babel preset-env target 설정하기

최신 크롬버전에 맞는 플러그인만 삽입하도록 변경하였다.

1
2
3
4
5
6
7
{
"presets": [
["@babel/preset-env", { "targets": "last 2 Chrome versions" }],
"@babel/preset-react"
],
"plugins": ["react-refresh/babel"]
}

추가로 해야할 것

  1. webpack-dev-server proxy 설정하기!
    나중에 cors로 인해 작업에 차질이 생길 수 있다. 미리 알아두어야 좋을 것 같다.
    webpack-dev-server proxy

느낀점

밑바닥에서 하나씩 차근차근 설정하니까 재밌고 오히려 욕심도 생긴다..!
webpack 객체의 property 자체에 대해 많이 알아봤는데, 시간이 없어서 다 적지 못하는게 아쉽다.
또 알게 된 것이 많았다.

Ref

Setup Webpack and Babel for React

Webpack 러닝 가이드

Webpack 공식문서

FE개발자의 성장 스토리 02 : Babel7과 corejs3 설정으로 전역 오염 없는 폴리필 사용하기

Babel Polyfill 적용하는 방법들