리액트를 처음 접하면서 바벨, 웹팩 등 모르는게 너무 많았습니다.
이게 정확히 뭔지 모르는 상태에서 CRA로만 편하게 리액트 프로젝트를 만들 때마다 답답했습니다. 모르는 단어가 하나둘씩 나올때마다 너무 스트레스 받아서 이대로는 프로젝트를 할 수 없다고 생각했습니다.
리액트가 어떻게 돌아가는지 하나하나 분석해가며 환경을 구축한 것을 잊지 않기위해 기록합니다.
$ yarn init -y
package.json
파일이 생성됨
<!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>
</body>
</html>
App.js
import * as React from "react";
const App = () => {
return (
<div class="helloDiv">
<p>Hello, World! ㅎㅇ</p>
<p>Hello, React!</p>
</div>
);
};
export default App;
index.js
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import App from "./App.js";
import "./index.css";
const appRouting = (
<Router>
<Switch>
<Route exact path="/" component={App} />
</Switch>
</Router>
);
ReactDOM.render(appRouting, document.getElementById("root"));
index.css
.helloDiv {
background-color: red;
width: 100px;
height: 100px;
}
$ yarn add react react-dom react-router-dom
JSX와 ES6+ 문법을 ES5 문법으로 바꿔준다.
$ yarn add -D @babel/core @babel/preset-env @babel/preset-react
@babel/core : 바벨 코어 패키지
@babel/preset
바벨은 plugin이 없으면 아무 동작도 하지 않기 때문에 따로 필요한 plugin을 설정해주어야 한다. 원래는 .babelrc 파일에 사용할 플러그인을 추가했어야 했는데, preset을 만들어 그럴 필요가 없게 만들었다.
@babel/preset-env : ES6+ 문법을 ES5로 트랜스파일링
@babel/preset-react : 리액트의 JSX를 JS로 트랜스파일링
@babel/preset-flow
@babel/preset-typescript
이 중 env와 react를 설치한다.
yarn add -D webpack webpack-cli webpack-dev-server
웹팩은 오직 JavaScript와 Json만 이해할 수 있다. 다른 타입의 파일들을 이해할 수 있게 번들링 해준다.
yarn add -D babel-loader css-loader style-loader file-loader html-loader
로더 는 파일을 해석하고 변환하는 과정에 관여하고, 플러그인은 결과물의 형태를 바꾸는 역할을 한다.
yarn add -D html-webpack-plugin clean-webpack-plugin
루트에 .babelrc 파일을 만들고 아래와 같이 프리셋을 설정해준다.
{
// Babel presets적용
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
루트에 webpack.config.js 파일을 만든다.
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
// 개발환경 mode : "development|production" 개발 환경과 배포 환경을 정할 수 있음
mode: "development",
// entry: 모듈의 의존성이 시작되는 부분. 빌드 작업을 시작할 부분을 명시한다.
entry: "./src/index.js",
//entry에서부터 시작하여 번들링된 파일을 어디에 저장할지(path), 어떤 파일이름으로 저장할지(filename) 명시
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js",
clean: true,
},
//module : 어떤 모듈을 사용할지 명시한다. test 는 어떤 파일에 적용될지 그 확장자를 명시한 것이다. 로더가 1개라면 loader 로, 2개 이상이라면 use 배열로 설정할 수 있다. exclude 로 로더를 제외할 대상을 적용할 수도 있다.
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: "/node_modules/",
loader: "babel-loader",
},
{
test: /\.css$/,
use: [{ loader: "style-loader" }, { loader: "css-loader" }],
},
{
test: /\.jfif$/,
loader: "file-loader",
options: {
name: "[name].[ext]",
},
},
// html관련 plugin
//minimize: true를 통해 html 코드를 최적화
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: {
minimize: true,
},
},
],
},
],
},
//plugins : 확장 기능을 넣을 수 있다.
// html-webpack-plugin : 번들이 완료된 파일을 <script/>를 이용해 로드한 html파일을 자동으로 생성해주는 플러그인
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html",
}),
],
// webpack-dev-server의 개발 서버 설정
devServer: {
host: "localhost",
port: 9000,
open: true, //개발 서버 실행 시 브라우저 오픈
},
};
"scripts": {
"build": "webpack -w",
"dev-server": "webpack-dev-server --open"
}
웹팩은 개발/프로덕션 모드가 있기 때문에 각각 다르게 설정해준다.
--progress 옵션은 번들링 진행 상태를 보기 위함이다.
$ yarn build
dist 폴더에 번들이 생겼다....
$ yarn dev-server
서버를 켰다...ㅠㅠㅠ
드디어 잘 수 있어요..,.. 웹팩, 바벨이 뭔지 알았고 리액트 앱이 어떻게 돌아가는지 조금이나마 알게되서 기쁩니당