Frontend/Article

CRA없이 React, Ts, Webpack 개발 환경 구축(+ eslint, prettier)

BeNI 2024. 6. 6. 19:05
728x90

 

 

 

 

 

오늘의 글

CRA(Create-React-App) 없이 React+Typescript 앱 환경 구축하기 !

 

옛날에는 Cra를 많이 썼었지만, 이제는 거의 쓰지 않는 추세이다. (2022/04 기준 으로 업데이트 되지 않고 있음)

또한 예전 리액트 공식문서에서는 CRA가 포함되어있었지만

새 React 공식문서에서는 이제 nextJs나 다른 프레임워크를 사용하라고 권장하고 있다.

https://react.dev/learn/start-a-new-react-project

 

Start a New React Project – React

The library for web and native user interfaces

react.dev

 

 

 

 

 

 

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 진짜 겁내 빨라요 추천 )

https://velog.io/@votogether2023/ts-loader%EB%A5%BC-esbuild-loader%EB%A1%9C-%EB%A7%88%EC%9D%B4%EA%B7%B8%EB%A0%88%EC%9D%B4%EC%85%98%ED%95%B4%EB%B3%B4%EC%9E%90

 

개발자 경험 개선하기 (2) - ts-loader를 esbuild-loader로 마이그레이션해보자!

보투게더 팀의 프론트엔드에서 최초로 선택한 loader는 ts-loader 였습니다. 해당 loader를 선택한 가장 큰 이유는, 프로젝트의 파일들이 거의 모두 TypeScript로 작성되기 때문이었습니다.타입의 안정성

velog.io

 

 

 

 

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로 제대로 웹 어플리케이션이 돌아가는지 확인해보자!

아름다운 Hello World..

 

 

 

 

 

npm run build를 하면, 빌드도 잘 되는 걸 확인할 수 있다!

 

 

 

 

 

 

번외)

webpack은 왜이리 복잡한지;;;

vite는 npm create vite@latest my-app -- --template react-ts

하면 끝인데...

 

 


 

 

이번 글은 여기까지!

 

 

잘못된 점 있거나 궁금한 점 있으면 언제든지 댓글 남겨주세요! :)

 

 

 

 

 

 

참고 링크

https://adjh54.tistory.com/83#google_vignette

https://yogjin.tistory.com/59

https://abangpa1ace.tistory.com/entry/Configs-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98%EB%A5%BC-%EC%84%A0%EC%96%B8%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-React-%EA%B8%B0%EC%A4%80

https://webpack.kr/guides/environment-variables/

https://webpack.kr/plugins/define-plugin/#root

 

728x90