webpack으로 React 프로젝트 빌드해보기 =)Frontend/webpack & babel2023. 10. 8. 18:13
Table of Contents
Why?
- CRA는 노맛..
- 무엇보다 실무에서 사용하고 있는데 어떻게 번들링 도구들이 동작하고 어떠한 plugin들이 실제로 상호작용을 통해 dev, prod를 이루는지 알 수 없다..!
- 일하면서 그냥 react 개발자로 제한되는 기분이였어요 .. =(
- 그리고 사실 너무 무거움
- 그래서 경험삼아 + 앞으로도 사용하기 위해 간단하게나마 직접 webpack을 사용해서 프로젝트를 빌드해보도록 하겠다!
step1. npm init & 의존성 설치
- 프로젝트를 생성한 후 프로젝트를 초기화하고 필요한 의존성을 설치하자
- 플러그인도 설치가 필요하지만 우선 구동에 필요한 필수적인 요소들만 설치해보자~
npm init (프로젝트 초기화 -> package.json 생성)
npm init -y
React
- React (react):
- React는 사용자 인터페이스를 구축하기 위한 자바스크립트 라이브러리입니다.
- React는 컴포넌트 기반 아키텍처를 사용하여 UI를 구성하고, 재사용 가능하고 관리 가능한 코드를 작성할 수 있게 해준다(Component).
- React DOM (react-dom):
- React DOM은 React 애플리케이션을 웹 브라우저에서 렌더링하기 위한 라이브러리.
- React DOM은 Virtual DOM을 사용하여 React 컴포넌트를 브라우저에 렌더링하고, 상호작용 가능한 웹 애플리케이션을 만들 수 있게 해준다.
npm install react react-dom
webpack
- Webpack (webpack):
- Webpack은 모듈 번들러로서, 프로젝트의 자원들을 번들링하여 최적화된 정적 자원으로 만들어준다.
- 여러 모듈 및 자원들을 하나의 파일로 결합하여 네트워크 요청 수를 줄이고, 성능을 향상시킨다.
- ES6+ 코드, CSS, 이미지 등과 같은 다양한 유형의 파일을 하나의 번들로 만들어준다.
- Webpack CLI (webpack-cli):
- Webpack 명령어를 사용할 수 있도록 해주는 커맨드 라인 도구.
- Webpack을 터미널에서 사용할 때 유용하며, 빌드 및 번들링 작업을 수행할 수 있게 한다
- Webpack Dev Server (webpack-dev-server):
- Webpack 개발 서버로서, 개발 중에 로컬 개발 서버를 제공하여 빠르고 편리한 개발 환경을 제공한다.
- 코드 수정 시 자동으로 빌드하고, 브라우저를 새로고침하지 않고도 변경된 내용을 실시간으로 확인할 수 있도록 도와준다.
- 또한, 핫 모듈 리플레이스(Hot Module Replacement)를 지원하여 소스 코드의 수정을 감지하고 변경된 모듈만 업데이트하여 빠르게 개발할 수 있다.
npm install -D webpack webpack-cli webpack-dev-server
babel
- Babel Loader (babel-loader):
- Babel Loader는 Webpack과 함께 사용되어 JavaScript 파일을 변환하고 번들링할 때 Babel을 통해 ES6+ 문법을 하위 호환성 있는 코드로 변환한다.
- webpack.config.js 파일의 module 부분에 사용됨!
- JavaScript 파일을 빌드할 때 Webpack이 Babel Loader를 사용하여 설정된 Babel 플러그인과 프리셋을 적용하고, 변환된 파일을 번들에 포함시킨다.
- Babel Core (@babel/core):
- Babel Core는 Babel의 핵심 기능을 담당하는 패키지로, 실제로 코드를 변환하고 해석하는 역할을 한다.
- Babel 플러그인과 프리셋은 Babel Core를 기반으로 동작하며, 코드 변환 작업은 Babel Core를 통해 이루어짐.
- Babel Preset Env (@babel/preset-env):
- Babel Preset Env는 환경에 따라 필요한 Babel 플러그인들을 자동으로 설정해주는 프리셋.
- 최신 JavaScript 문법을 이전 버전의 JavaScript로 변환하고, 필요한 폴리필(Polyfill)을 제공하여 환경 호환성을 유지한다.
- Babel Preset React (@babel/preset-react):
- Babel Preset React는 React 애플리케이션에서 JSX 문법을 변환하기 위한 프리셋.
- JSX 코드를 React.createElement() 함수 호출로 변환하여 React가 이해할 수 있도록 한다. (Transpile)
npm install -D babel-loader @babel/core @babel/preset-env @babel/preset-react
style & 기타
- clean-webpack-plugin:
- 이 플러그인은 Webpack 빌드 이전에 이전 빌드 결과물을 지워주는 도구 -> 빌드 디렉토리를 깨끗하게 유지할 수 있어 불필요한 파일 충돌을 방지하고 디스크 공간을 절약한다
- html-webpack-plugin
- script 태그를 사용하여 body에 모든 webpack 번들을 포함하는 HTML5 파일을 생성!
- HTML 파일을 생성하거나 기존 HTML 파일을 기반으로 새 HTML 파일을 생성하여 빌드 결과물에 자동으로 연결한다. 설정에 따라 빌드된 CSS 및 JavaScript 파일에 대한 링크를 자동으로 삽입한다.
- HTML 템플릿 사용: HtmlWebpackPlugin은 지정한 HTML 템플릿 파일을 기반으로 HTML을 생성한다. 일반적으로 프로젝트에서 사용하는 기본 템플릿을 지정하고, 해당 템플릿에 빌드 결과물에 대한 자동 삽입 위치를 설정할 수 있다.
- 자동 파일 연결: 템플릿에서 지정한 위치에 CSS, JavaScript 파일과 같은 빌드 결과물을 자동으로 연결해준다.
이렇게 함으로써 개발자는 직접 파일 경로를 관리하지 않아도 되며, Webpack이 자동으로 최신 파일 경로를 인식하여 삽입한다. - 캐싱 관리: HtmlWebpackPlugin은 빌드 결과물에 해시를 추가하여 파일이 변경될 때마다 브라우저가 새로운 파일을 가져오도록 한다. 이는 캐싱을 통한 성능 최적화를 가능하게 한다.
- css-loader:
- CSS 파일을 JavaScript 모듈로 변환하는 Webpack 로더.
- 이로써 JavaScript 코드 안에서 CSS 스타일을 import하거나 사용할 수 있다.
- sass-loader:
- Sass(Syntactically Awesome Stylesheets)는 CSS의 확장 버전으로, 변수, 중첩, mixin 등을 사용할 수 있게 한다.
- sass-loader는 Webpack과 함관하여 Sass 파일을 컴파일하고 일반 CSS로 변환!
- mini-css-extract-plugin
- CSS 파일을 별도로 추출하여 단일 파일로 생성하는 역할을 한다. 일반적으로는 CSS를 번들링한 JavaScript 파일에 포함되지 않고, 별도의 CSS 파일로 생성하여 로딩 성능을 최적화한다
- 주로 프로덕션에서 사용하는 것이 일반적이다.!! CSS를 별도의 파일로 추출하여 효율적인 캐싱, 로딩 및 성능 최적화를 가능하게 하기 때문이다.
- 일반적으로 개발환경에서는 CSS를 번들링된 Javascript 파일에 포함해서 빠른 빌드와 디버깅을 위해 사용하기 때문에 개발중에는 CSS를 별도 파일로 추출하지 않아도 되어 편리하다!
- 프로덕션에서는 CSS 파일을 별도로 추출해서 로딩 성능을 최적화하고 캐싱을 향상시키기 위해 사용된다. 사용자가 웹 사이트 방문할 때 캐싱된 CSS 파일을 로드하기 때문!
- 따라서 개발환경에서는 style-loader와 같은 방법으로 CSS를 번들링된 Javascript 파일에 포함시켜 개발 경험을 개선시키고 프로덕션에서는 Plugin을 이용해 사용자의 경험을 개선!
npm install -D clean-webpack-plugin html-webpack-plugin css-loader sass-loader mini-css-extract-plugin
+++ webpack-merge
- dev/prod의 번들링 결과물을 다르게 하기 위해서 사용해보자~
- dev/prod의 공통된 설정을 작성할 파일을 만들고 dev/prop의 각각의 설정을 위한 파일에서 webpack-merge 기능을 사용하면 공통된 부분에 dev/prod만을 위한 설정을 해줄 수 있다
- 사실 요거 없이 중복을 허용해서 webpack 설정 파일을 만들어도 상관없긴하다 ㅇㅅㅇ
npm install -D webpack-merge
step2. babel & webpack 설정파일 만들기
- react는 jsx를 사용하므로 babel 설정이 필요하다..!
- dev/prod를 각각 설정할 것이므로 공통으로 사용할 webpack.common.js, development를 위한 webpack.dev.js, production을 위한 webpack.prod.js 파일을 만들어서 내용을 작성해보자!
babel.config.js
- webpack 설정에서 babel-loader를 불러와서 jsx를 js로 이해시켜줘야 하는데, .babel.config.js, .babelrc와 같은 Babel 설정 파일을 생성하여 React와 ES6+ 문법을 변환하도록 설정해야 한다!
- preset -> Babel 플러그인을 묶어놓은 설정 그룹
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', "@babel/preset-react"],
};
// 아래처럼 runtime 옵션을 추가하면 jsx 파일마다 import React from "react"를 하지 않아도 된다!
module.exports = {
presets: [
'@babel/preset-env',
['@babel/preset-react', { runtime: 'automatic' }],
],
};
- 위와 같이 작성하면 아래처럼 babel-loader를 사용할 때 preset의 내용이 들어간다
use: {
loader: 'babel-loader',
},
webpack.common.js
- dev/prod의 공통된 webpack 설정을 작성!
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: 'public/index.html',
}),
],
};
webpack.dev.js
- 주석을 읽어봅시당 =)
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
// dev 용 webpack 설정 명시
mode: 'development',
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
],
},
// 개발 서버(devServer) 설정
// static: 개발 서버가 정적 파일을 제공할 기본 디렉토리를 './dist'로 설정.
// port: 개발 서버의 포트를 3000으로 설정합니다.
// open: 개발 서버가 실행될 때 브라우저를 자동으로 열도록 설정합니다.
// historyApiFallback: 설정하지 않으면 "/" 경로만 인식하고 나머지는 오류로 판단!
// 리액트는 SPA 방식이어서 URL의 시작 주소(=index.html)만 갖고 있는데,
// 웹의 history API를 사용해서 여러가지 URL이 있는 것 처럼 만들어 줄 수 있다.
devServer: {
static: './dist',
port: 3000,
open: true,
historyApiFallback: true
},
// 소스맵 설정
// devtool: 개발 환경에서 디버깅을 용이하게 하기 위해 'inline-source-map'을 설정.
// 이렇게 하면 소스맵 파일을 생성하여 원본 소스 코드와 번들된 코드 간의 매핑을 제공한다. -> console에 실제 코드위치가 보임!
devtool: 'inline-source-map',
});
webpack.prod.js
- dev와 다르게 Css 파일을 처리하기 위해 별도의 플러그인 사용 !
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = merge(common, {
mode: 'production',
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: 'styles.css',
}),
],
});
step 3. index.html, index.js, app.js 파일 생성하기
- webpack.common.js에서 entry로 작성한 어플리케이션의 시작점인 index.js 파일에서 App.js의 내용을 index.html에 렌더링하기 위해 각각의 파일들을 만들어주자..!
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
// ReactDOM.render 함수 첫번째 파라미터를 두번째 파라미터에 렌더링
// App.js를 index.html에 랭더링
// React 컴포넌트를 실제 HTML 문서 내의 DOM 요소에 렌더링!
// 'root' 에 App.js 를 렌더링!!
// index.html 파일 내에서 정의된 root 요소(<div id="root"></div>)에 React 애플리케이션을 마운트!
ReactDOM.render(<App />, document.getElementById('root'));
src/App.js
import React from 'react';
function App() {
return (
<div>
<h1>Hello, React!</h1>
</div>
);
}
export default App;
public.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
step 4. package.json에 명령어 추가하기
- 여기까지 잘 따라왔다면 이제 리액트 프로젝트를 실행할 준비가 모두 끝났다..!
- 파일 구조는 아래와 같을 것이다
- dev 서버에서 실행하기 위한 명령어와 prod에 build할 파일을 생성하는 명령어를 추가하자!!
"start": "webpack serve --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
package.json
{
"name": "duckgugong",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack serve --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.23.2",
"@babel/preset-env": "^7.23.2",
"@babel/preset-react": "^7.22.15",
"babel-loader": "^9.1.3",
"clean-webpack-plugin": "^4.0.0",
"css-loader": "^6.8.1",
"html-webpack-plugin": "^5.5.3",
"mini-css-extract-plugin": "^2.7.6",
"sass-loader": "^13.3.2",
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1",
"webpack-merge": "^5.10.0"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}
- npm run start 혹은 yarn start를 입력하면 프로젝트를 띄울 수 있다!
'Frontend > webpack & babel' 카테고리의 다른 글
Babel (0) | 2023.10.08 |
---|---|
Loader / Plugin (1) | 2023.10.08 |
Entry(index.js) / Output (0) | 2023.09.03 |
webpack (1) | 2023.08.21 |
webpack과 babel 리액트 프로젝트 생성 (0) | 2022.06.04 |
@덕구공 :: Duck9s'
주니어 개발자에욤
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!