지금까지 리액트 프로젝트를 생성할 때 CRA로 줄곧 진행을 했었는데, 이번에는 CRA없이 직접 웹팩과 바벨설정을 하면서 리액트 프로젝트 내부에서 어떤 일이 발생하는지 이해하고자 진행을 해봤습니다.
react-webpack5라는 이름으로 폴더를 생성했습니다.npm init -y
폴더안에 아래와 같은package.json파일이 생성 될 것입니다.
{
"name": "react-webpack5",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
npm i react react-dom
package.json 파일의 디펜더시 항목에 추가됩니다. "dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
}
npm i -D @babel/core @babel/preset-env @babel/preset-react babel-loader file-loader css-loader style-loader webpack webpack-cli html-webpack-plugin webpack-dev-server
package.json 파일을 확인해보면 devDependencies에 아래와 같이 추가됐음을 확인 할 수 있습니다. "devDependencies": {
"@babel/core": "^7.15.5",
"@babel/preset-env": "^7.15.4",
"@babel/preset-react": "^7.14.5",
"babel-loader": "^8.2.2",
"css-loader": "^6.2.0",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.3.2",
"style-loader": "^3.2.1",
"webpack": "^5.52.0",
"webpack-cli": "^4.8.0"
"webpack-dev-server": "^4.1.1"
}
.babelrc 파일을 생성해 줍니다. jsx에서 일반 js로 리액트 코드를 변환하기 위해 필요합니다.//.babelrc
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
}
현재 파일 구조는 다음과 같습니다.
webpack.config.js 파일을 생성합니다. 이 웹팩 파일은 기본적으로 브라우저가 아닌 노드 환경에서 실행됩니다. 따라서 여기에 바닐라 js 코드를 작성할 수 있습니다.파일에는 아래의 코드를 넣어주세요.
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: "development",
output: {
path: path.join(__dirname, "/dist"),
filename: "index.bundle.js",
},
devServer: {
port: 3000,
liveReload: true,
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /nodeModules/,
use: {
loader: "babel-loader",
},
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
],
},
plugins: [new HtmlWebpackPlugin({ template: "./public/index.html" })],
};
output 에서는 파일이 번들되면 어디로 보내야 하는지 언급합니다.path에는 번들 파일이 저장될 디렉토리 이름이 지정되어 있습니다. 폴더 이름을 dist라고 지었는데, 이것은 일반적인 관행입니다.filename은 웹팩이 실행된 후 생성되는 새로운 번들 파일에 대해 설정한 이름입니다(기본적으로 모든 js 코드를 하나의 파일로 묶습니다).devServer 어플리케이션을 구축하는 데 훨씬 많은 시간이 걸리는 프로덕션 모드와 반대되게 어플리케이션을 신속하게 개발하기 위해 사용됩니다.port를 사용하면 원하는 포트 번호를 설정할 수 있습니다. 저는 3000으로 설정했습니다.liveReload는 파일에 변경 사항이 있을 때 바로 반영해서 출력해 줍니다.module은 파일 번들링 규칙을 지정하는 옵션입니다.test는 특정 로더의 대상이 되어야 하는 파일의 확장자를 언급하는 경우입니다. 모든 .js 또는 .jsx 파일은 바벨 로더에 의해 번들되어야 합니다.exclude 번들러가 무시해야 하는 파일을 지정합니다.css 파일도 마찬가지입니다.use :['style-loader', 'css-loader'] 배열은 정확한 순서로 작성되어야 합니다.css-loader를 실행합니다.style-loader를 실행합니다.plugins 마지막으로 우리는 HtmlWebpackPlugin이라고 불리는 플러그인을 추가하는데, 이것은 웹팩이 html 파일 템플릿을 알 수 있도록 합니다.복잡한 부분이 완료되었으니 이제 리액트 파일을 추가해주도록합시다.
public폴더와 src폴더를 생성해주고, 각 폴더에 아래와 같이 파일을 추가해주세요.public
-index.html
src
-index.js
-App.js
-App.css
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React Webpack5 App</title>
</head>
<body>
<div id="app"></div>
<script src="index.bundle.js"></script>
</body>
</html>
import React from "react"
import ReactDom from "react-dom"
import App from "./App"
import "./App.css"
ReactDom.render(<App />, document.getElementById('app'))
간단한 내용을 추가합니다.
import React from "react"
function App() {
return (<div>
<h2>Welcome to React App</h2>
<h3>Date : {new Date().toDateString()}</h3>
</div>)
}
export default App
h2{
color: teal
}
이제 스크립트 실행을 위해 package.json파일을 수정해야합니다.
"scripts": {
"serve": "webpack serve --mode development",
"build": "webpack --mode production"
}
npm run serve
개발 모드에서는 아래와 같이 번들된 코드가 정렬되어 나옵니다.
localhost:3000
npm run build
이로써 create-react-app없이 Webpack5환경에서 React 프로젝트를 시작할 수 있게되었습니다.
간단하지는 않지만 웹팩과 바벨에 대한 이해도도 올라가고 정말 필요한 옵션들만 골라서 추가해줄 수 있어서 추후 최적화하기도 좋을 것 같네요. 읽어주셔서 감사합니다:)