CRA로만 리액트 셋팅하다가 과제하면서 CRACO로 셋팅을 해본적이 있다.
CRACO는 CRA보다 빌드 속도가 더 빨랐는데, 이유는 CRACO가 Webpack과 Babel 설정을 더욱 최적화하여 불필요한 작업을 줄이고, 더욱 최적화된 빌드 결과물을 생성하기 때문이었다.
그럼 웹팩과 바벨만 사용하여 프로젝트를 빌드하면 더 빠를까? 란 생각이 문득 들었는데
보장되진 않는다.
설정을 잘못하거나 최적화하지 않으면 빌드 속도가 느려질 수 있기 때문이다.(모든것은 나의 설정대로~)
뭔가 오기 생기게 한다. 내가 설정한게 더 빨랐으면 좋겠다. 호호..
어쨋든 웹팩과 바벨에 대한 이해도도 높일겸 웹팩+바벨로 리액트 개발환경 셋팅하기!를 시작해본다.
npm init
먼저 프로젝트를 시작하기 전, 프로젝트 패키지를 초기화하여 생성해주자.
해당 명령어를 입력하면 package.json 파일이 생성된다.
npm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/preset-react
바벨 관련 패키치들을 설치한다.
react는 브라우저가 읽지 못하고 또 최신 문법이 적용된 Java Script도 브라우저마다 지원되는게 다르기 때문에 babel을 이용하여 최신코드 -> 구형코드로 트랜스파일링 해야한다.
@babel/core : Babel 도구로서 최신 코드를 구형 코드로 옮기는 방법을 알고 있는 도구
내부적으로 core-js 패키지를 활용하는데 core-js는 결국 다수의 폴리필들이 내장된 거대한 패키지다.
core-js를 가져오기하면 모든 브라우저에서 작동하는 세상의 모든 JavaScript 기능을 사용할 수 있지만,
예시로, 나는 지원되지 않는 코드중 프로미스만 쓰는데, 이 지원되지 않는 프로미스가 작동하도록 하기 위해 애 사용하지 않는 수많은 기능이 추가된다. 따라서 core-js/features/promise처럼 필요한 부분만 가져올 수 있게 할 수 있지만, 이는 우리가 수동으로 제어해줘야 한다......
그런데 preset-env를 쓰면?!
@babel/preset-env : 어떤 기능이 어떻게 컴파일링 되는지를 제어하는 사전 설정,
@babel/core가 JavaScript 코드를 컴파일할 때, 지정한 환경에서 실행 가능한 코드로 변환하기 위해 필요한 변환을 결정하고 적용하는데, @babel/preset-env는 지정한 환경과 호환되는 최소한의 변환만 적용하므로, 개발자는 수동으로 모든 변환을 설정할 필요가 없음
Babel (공식 문서): https://babeljs.io/docs/en/
babel/preset-env 문서: https://babeljs.io/docs/en/babel-preset-env
core-js Docs: https://github.com/zloirock/core-js
npm install --save-dev webpack webpack-cli webpack-dev-server
웹팩과 웹팩 cli, 웹팩 dev server를 설치한다. webpack-cli는 cli에서 웹팩을 사용하기 위한 패키지, webpack-dev-server는 코드를 수정하면 자동으로 메모리상에 재빌드를 해주기 때문에 빠르고 편리한 개발을 도와주는 패키지이다.
npm install --save-dev html-webpack-plugin css-loader style-loader file-loader babel-loader
웹팩 설정에 필요한 로더, 플러그인 패키지들을 설치한다.
babel-loader 문서: https://github.com/babel/babel-loader
npm install react react-dom
마지막으로 react와 react-dom을 설치하면! 설치할건 다 끝났다.
생각보다 리액트를 동작시키기 위한 패키지가 별로 없다.
1) JSX를 사용하지 않을때
return React.createElement('div',{},React.createElement('h2',{},"let's go")
React.createElement(Expense,{items:expenses})
)
2) JSX를 사용할때
return(
<div>
<h2>let's go</h2>
<Expense items={expenses}/>
</div>
)
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: path.join(__dirname, 'src', 'index.jsx'),
// index.js가 엔트리면 js로, tsx면 tsx로 맞춰줘야 한다.
mode: 'development', //개발모드 만약 프로덕션이면 production으로
output: {//빌드후 아웃풋이 dist폴더에 넣어진다.
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.?(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
//type-script쓴다면 '@babel/preset-typescript'도 설치해서 넣어주고
},
},
resolve: {
extensions: ['', '.js', '.jsx'], //확장자도 '.tsx'넣어준다.
},
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|jp(e*)g|svg|gif)$/,
use: ['file-loader'],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'public', 'index.html'),
//HTML 파일을 생성해주는 플러그. template 옵션을 통해 기존에 작성된 HTML 파일을 가져와서 빌드 결과물에 자동으로 삽입
}),
new webpack.HotModuleReplacementPlugin(),
//코드 수정 시 자동으로 모듈을 교체하여 브라우저의 새로고침 없이도 수정된 결과를 실시간으로 확인할 수 있도록 도와줌
],
devServer: {
hot: true, //핫 모듈 리플레이스먼트(Hot Module Replacement)의 기능을 활성화 : 수정된 모듈만 다시 로드하여 빌드 시간을 단축
//참고 : [webpack-dev-server] "hot: true" automatically applies HMR plugin, you don't have to add it manually to your webpack configuration.로 해당 부분 설정안해도 알아서 최적화 해주는 듯 하다.
host: 'localhost',
port: 3000,
},
> };
//"start": "webpack-dev-server --mode development" 추가
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --mode development"
},
{
"presets": ["@babel/env", "@babel/preset-react"]
}
두개 다 열려있어서 헷깔릴까봐 집어주자면, index와 app은 src하위 폴더 component가 아닌 src안에 있다.
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
import React from "react";
const App = () => {
return (
<div>
<p>non auto setting</p>
<p>fun?</p>
</div>
);
};
export default App;
이렇게 설정하고 npm run start하면 개발서버로 잘 보인다~!
워낙 프로젝트 셋팅들이 잘 구성되어 있다보니, 생각해보면 babel과 webpack 들은 스쳐지나 들어만 본 것 같다. 사실 최적화와 관련된 부분이 빌드로 번들러가 중요한 역할을 하는데도 말이다. 바벨도 폴리필 등을 지원해주면서 내 코드가 읽히는게 아니고 내 코드 -> 변환 코드가 읽히는건데 말이다.
생각해보면 둘 다 굉장히 코어 역할을 하는데 호로록~ 지나가버린듯 했다. 이번기회에 어떤 역할을 할 수 있는지 알 수 있어서 좋았고, 조금 더 공부해서 최적화까지 커스텀해보고 싶다.
점점 시간이 지날수록 설정 파일들을 만져야 될때가 많아지고 있다. 써보고 싶은 라이브러리, 써보고 싶은 스택 등 섞이고 운영체제 별로도 설정에서 오류가 들쑥날쑥 할 때가 생기는데 그때마다 설정 방법 뒤져가면서 맞춰주고 있다. 그때마다 이번 경험을 토대로 하나씩 하나씩 맞춰보면서 설정에 대한 이해도를 높일 수 있을 것 같다.
처음은 어렵지만, 지나보면 아무것도 아닐때가 올때까지..🍋