CRA없이 React, Ts, Webpack 개발 환경 구축(+ eslint, prettier)
오늘의 글
CRA(Create-React-App) 없이 React+Typescript 앱 환경 구축하기 !
옛날에는 Cra를 많이 썼었지만, 이제는 거의 쓰지 않는 추세이다. (2022/04 기준 으로 업데이트 되지 않고 있음)
또한 예전 리액트 공식문서에서는 CRA가 포함되어있었지만
새 React 공식문서에서는 이제 nextJs나 다른 프레임워크를 사용하라고 권장하고 있다.
https://react.dev/learn/start-a-new-react-project
Webpack, vite, rollup 등 다양한 번들러들이 있긴하지만
필자는 CRA에서 쓰고 있는 웹팩을 이용해서 개발환경 구축을 해보려한다.
(요새는 vite가 인기가 많아졌긴했는데 그래도 웹팩으로 !!)
* 번들러: 웹 애플리케이션을 개발하기 위해 필요한 HTML, CSS, JS 등의 모듈화된 자원들을 모아서,
하나 혹은 최적의 소수 파일로 결합(번들링)하는 도구
(출처: https://www.heropy.dev/p/x8iedW)
그럼 시작!
1. package.json 만들기
npm init -y
init -y 하면 default 값으로 package.json이 만들어진다
2. 필요한 라이브러리 설치
1) React 설치
$ npm i react react-dom
2) Typescript 설치
$ npm i -D typescript @types/react @types/react-dom
- typescript
- @types/react
- @types/react-dom
3) loader 설치
$ npm i -D esbuild-loader fork-ts-checker-webpack-plugin
tsx를 컴파일, 트랜스파일링 하기 위해 ts-loader, babel-loader, esbuild-loader 셋 중 하나를 사용할 수 있는데,
본 글에서는 esbuild-loader를 사용했다.
esbulid-loader는 타입체킹을 안해주기때문에 fork-ts-checker-webpack-plugin 플러그인 까지 추가
(esbuild-loader 진짜 겁내 빨라요 추천 )
babel-loader쓰고 싶으신 분은 아래 참조
babel 관련 설치
$ npm i -D babel-loader @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript
설치해주고 루트에 babel.config.json 파일 만들어준다
{
"presets": [
[
"@babel/preset-react",
{
"runtime": "automatic"
}
],
"@babel/preset-env",
"@babel/preset-typescript"
]
}
React 17부터 JSX Transform 으로 인해서 import React from 'react' 를 모든 React 파일에 작성할 필요가 없어졌다.
그러나 Babel에서 이를 자동으로 변환해주지 않기 때문에 { "runtime": "automatic" } 부분을 작성해야 한다.
4) webpack 설치
npm i -D webpack webpack-cli webpack-dev-server html-webpack-plugin css-loader mini-css-extract-plugin file-loader dotenv-cli
- webpack
- webpack-cli: webpack을 더 쉽게 사용할 수 있도록 다양한 명령을 제공
- webpack-dev-server: 개발용 웹 서버
- html-webpack-plugin: 번들링 후 html에 번들링된 js를 로드시킴
- css-loader: js파일에서 css를 불러오기 위해 사용, css파일을 읽기 위한 로더
- mini-css-extract-plugin (style-loader설치해도 됨) : css 파일을 별도로 만들어서 html 에 로드
- style-loader는 html style태그 안에 css 코드를 삽입함.
- file-loader: js파일에서 파일 불러올 때 처리하기 위한 로더
- dotenv-cli: 환경변수 설정을 위한 플러그인
5) prettier, eslint 설치
npm i -D prettier eslint@8 eslint-plugin-react-refresh eslint-plugin-jsx-a11y eslint-plugin-react-hooks @typescript-eslint/eslint-plugin @typescript-eslint/parser
- prettier: 코드 포맷팅, 일관된 코드 스타일을 위해 사용
- eslint: 코드 포맷팅, 코드 퀄리티를 위해 사용(아래 플러그인과 호환되기 위해 8버전 설치)
- eslint-plugin-react: 기본 react eslint 플러그인
- eslint-plugin-react-hooks: 리액트 훅 코드 포맷팅 용도
- eslint-plugin-react-refresh: 리액트에서 코드 변경시 바로 업데이트 해줌
- eslint-plugin-jsx-a11y: 개발자가 놓치기 쉬운 접근성을 위한 플러그인
- @typescript-eslint/eslint-plugin : TypeScript 코딩 스타일 및 코드 품질 향상 용도
- @typescript-eslint/parser: ESLint가 TypeScript 코드를 이해할 수 있도록 해주는 파서
* eslint 플러그인은 vite-react-ts 세팅시 설정해주는 플러그인을 참고함
eslint 룰은 각자 환경에 맞게 세팅하는 걸 추천
3. 설정 파일 작성
1) .prettierrc
// .prettierrc
{
"printWidth": 140,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"arrowParens": "always",
"singleQuote": true,
"trailingComma": "es5",
"bracketSameLine": false,
"bracketSpacing": false
}
* 참고) vsCode prettier 적용방법
1. 확장 프로그램에서 아래 플러그인 깔아준다
2. ctrl + , 으로 설정 열어주고 default formatter 검색
default formatter에 prettier 설정
3. format on save 검색후 저장할 때마다 prettier 적용되도록 설정
2) .eslintrc.cjs
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
"plugin:react/recommended",
"plugin:react/jsx-runtime",
'plugin:react-hooks/recommended',
'plugin:@typescript-eslint/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh', 'jsx-ally'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
3) tsconfig.json
(vite react-ts, cra tsconfig 참고함)
{
"compilerOptions": {
"target": "es6",
"useDefineForClassFields": true,
"lib": [
"ES2020",
"DOM",
"DOM.Iterable"
],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": [
"src"
]
}
4) .env
프로젝트 루트에 .env(로컬용), .env.production(배포용)을 만들어준다.
// .env
MODE=development
PORT=3000
// .env.production
MODE=production
PORT=3000
해당 변수는 react상에서는 사용 불가하다.
빌드물 안에서 사용하려면 따로 웹팩 설정이 필요 ! (아래 웹팩 설정 참조)
5) ⭐webpack.config.js⭐
// webpack.config.js
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const path = require('path');
module.exports = {
mode: process.env.MODE,
entry: './src/index.tsx',
resolve: {
// 번들링을 할 파일 설정
extensions: ['.js', '.jsx', '.ts', '.tsx',],
},
module: {
// loader 설정 - 등록한 로더의 뒤의 요소부터 번들링에 반영
// node_modules 제외
rules: [
{
test: /\.(ts|tsx)?$/,
use: ['esbuild-loader'],
exclude: '/node_modules/',
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
{
test: /\.(png|jpe?g|gif|svg)$/i,
loader: 'file-loader',
options: {
name: 'assets/[contenthash].[ext]',
},
},
],
},
output: {
path: path.join(__dirname, '/build'),
filename: 'bundle.[hash].js',
},
plugins: [
new ForkTsCheckerWebpackPlugin(),
// 번들한 css파일과 js파일을 html 파일에 link 태그, script태그로 추가
new HtmlWebpackPlugin({
template: 'public/index.html',
}),
new MiniCssExtractPlugin({
filename: 'css/[name].css',
}),
// 환경 정보를 제공
new webpack.EnvironmentPlugin(['MODE', 'PORT'])
],
devServer: {
host: 'localhost',
port: process.env.PORT,
open: true,
historyApiFallback: true,
hot: true, // hot : 모듈의 변화된 부분만 서버에 자동으로 반영
},
devtool: 'eval-cheap-source-map'
};
요기까지 했으면,
package.json에 아래 스크립트를 추가해준다.
"scripts": {
"start": "dotenv -e .env webpack-dev-server --progress",
"build": "dotenv -e .env.production webpack --progress"
},
4. 파일 작성
1) public/index.html
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
name="viewport">
<meta content="ie=edge" http-equiv="X-UA-Compatible">
<title>React-Ts-Webpack</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
2) src/index.tsx
import React from 'react';
import App from './App';
import ReactDOM from 'react-dom/client';
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
3) src/App.tsx
function App() {
return <div>Hello World!</div>;
}
export default App;
이제 npm run start로 제대로 웹 어플리케이션이 돌아가는지 확인해보자!
npm run build를 하면, 빌드도 잘 되는 걸 확인할 수 있다!
번외)
webpack은 왜이리 복잡한지;;;
vite는 npm create vite@latest my-app -- --template react-ts
하면 끝인데...
이번 글은 여기까지!
잘못된 점 있거나 궁금한 점 있으면 언제든지 댓글 남겨주세요! :)
참고 링크
https://adjh54.tistory.com/83#google_vignette
https://webpack.kr/guides/environment-variables/
https://webpack.kr/plugins/define-plugin/#root