프론트엔드 개발/React.js

CRA를 Vite로 마이그레이션 하기

snowman95 2023. 1. 15. 20:40
728x90
반응형

차세대 프론트엔드 Tool Vite

 

Vite

Next Generation Frontend Tooling

vitejs.dev

이 게시물은 기존에 CRA(Create-React-App) 로 구축된 프로젝트에서 vite로 마이그레이션 하는 사람들을 대상으로 한다.

글을 쓰는 현재 시점으로 vite 는 4 버전대 이다.

 

CRA(Create-React-App) 대신에 왜 vite 를 써야 하는지는 아래의 테스트 결과로 대신 하겠다.

 

테스트 👨‍🔬

CRA vs vite 

회사 내 프론트엔드 프로젝트를 로컬 환경에서 cra, vite로 각각 start, build 시도

  • CRA (현재)
    • App Start Time : (대략 3.6초 ?)
      • webpack 5.74.0 compiled successfully in 3593 ms
    • Build Time : 2분 16초
  • Vite v4
    • App Start Time : 1초
    • Build Time : 24초

빌드 타임에서 엄청나게 유의미한 결과가 나왔다... 👏

webpack 로 1번 빌드하는 동안 vite 로 빌드하면 무려 6번 이나 빌드할 수 있는 것이다...!

개인 프로젝트 단위에서는 아무리 많이 빌드를 해도 GithubAction 같은 CI/CD 도구의 빌드타임이 많이 쌓여서 과금되는 경우가 없을 테지만, 회사에서는 아슬아슬하거나 과금되는 곳이 많을 거다.

 

CRA 에서 에러만 안나면 vite 로 바꾸는데 30분도 안걸린다. 이걸로 돈 나갈 거 안나가게만 해도 엄청난 성과이며 이득이다.

 

 

마이그레이션 과정

vite 패키지 설치

yarn remove react-scripts @craco/craco craco-alias

yarn add -D @vitejs/plugin-react vite
  • craco 를 사용 중이었다면 craco 관련 패키지 및 craco.config.js 파일 삭제 해야 한다.

 

스크립트 교체

"scripts" : {
  "start" : "vite"
  "build" : "vite build"
}

 

파일 위치 이동 및 내용 수정

  • public/index.html → /index.html
  • %Public_URL% 로 작성된 것을 실제 경로로 변경 필요
from
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link type="text/css" rel="stylesheet" href="%PUBLIC_URL%/reset.css" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo.jpg" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />

to
<link rel="icon" href="/favicon.ico" />
<link type="text/css" rel="stylesheet" href="/reset.css" />
<link rel="apple-touch-icon" href="/logo.jpg" />
<link rel="manifest" href="/manifest.json" />
  • 집입점 추가
<body>
  <div id="root"></div>
  <script type=”module” src=”/src/index.tsx”></script>
</body>

 

vite.config.ts 파일 추가

import {defineConfig} from 'vite';
import react from "@vitejs/plugin-react";
import viteTsconfigPaths from 'vite-tsconfig-paths';
import svgrPlugin from 'vite-plugin-svgr';

export default defineConfig({
  plugins: [react(), viteTsconfigPaths(), svgrPlugin(), ];
})

 

플러그인 설치 및 적용

종류가 많다. 원하는 것 설치해주면 된다.

yarn add -D vite-tsconfig-paths vite-plugin-svgr vite-plugin-eslint vite-plugin-env-compatible
  • vite-plugin-svgr : SVG 그래픽을 리액트 컴포넌트처럼 사용
  • vite-plugin-packgage-version : package.json 에서 패키지 버전을 환경 변수로 삽입
  • vite-plugin-eslint : ESLint 관련 오류 알려줌
  • vite-tsconfig-paths : tsconfig.json에 정의된 paths 매핑사용
  • vite-plugin-env-compatible : 환경변수가 VITE 로 시작하지 않고 REACT_APP 으로 시작쓸 수 있게 해줌

참고로
@vitejs/plugin-react 안에 react-refresh 와 동일 역할하는 @vitejs/plugin-react-refresh 도 내장되어 있어서 또 설치 안해도 된다.

 

 

 

환경변수 이름 변경

  • REACT_APP_ 접두사를 VITE_ 로 변경 해주어야 합니다.
  • 그게 귀찮다면 vite-plugin-env-compatible 라이브러리 설치하면 REACT_APP 접두사 그대로 사용할 수 있습니다.
  • 설치후 아래와 같이 설정파일에 추가해주면 됩니다.
  • 그러나 환경변수 불러오는 방식은 아래와 같이 변경해주어야 합니다.
    • process.env → import.meta.env
// vite.config.ts 

import envCompatible from 'vite-plugin-env-compatible'

export default defineConfig({
  envPrefix: "REACT_APP_", 
  plugins: [ // ...other plugins envCompatible(), ], 
})

 

환경변수에 타입 추가 (안해도 됨. 선택사항. 이런 것도 가능하다는 것임)

if (import.meta.env.DEV) {
  // do something in development mode only
}

if (import.meta.env.PROD) {
  // do something in production mode only
}
interface ImportMetaEnv { 
  readonly VITE_TOKEN: string; 
  readonly VITE_CLIENT_ID: number; 
} 

interface ImportMeta { 
  readonly env: ImportMetaEnv; 
}

 

 

서버 시작 시 브라우저 앱 자동으로 열기

// vite.config.ts 

export default defineConfig({ 
  ... 
  server: { 
    open: true, 
  }, 
});

 

기본 포트 변경

// vite.config.ts

export default defineConfig({ 
  ... 
  server: { 
    port: 3000, 
  }, 
});

 

/src/react-app-env.d.ts → /src/vite-env.d.ts 파일명 변경 및 내용 수정

from
/// <reference types="react-scripts" />

to
/// <reference types="vite/client" />

 

tsconfig.json 변경

  • types에 vite/client 를 추가
    • TS에 제공하는 특별한 Vite 브라우저 기능에 대해 알려줍니다.
    • "types": ["vite/client"],
  • "isolatedModules": true 옵션 추가
    • 기능적으로 Vite 에서 아직 지원하지 않는 최신 TS가 있기 때문

 

node_modules 삭제 후 재설치 (꼭 해야함!!!!)

rm -rf node_modules

yarn install

 

 

이슈

일부 라이브러리에서 특정 함수를 중괄호로 가져오는 게 안되는 경우가 있음.

from
import { sanitize } from 'dompurify'

export const htmlParser = (content: string) => {
    return content ? Parser(quillDecodeIndent(sanitize(content, config))) : ''
}

to
import DOMPurify from 'dompurify'

export const htmlParser = (content: string) => {
    return content ? Parser(quillDecodeIndent(DOMPurify.sanitize(content, config))): ''
}

컴포넌트 import 위치를 react-pdf/dist/esm/entry.vite 로 변경

import { pdfjs, Document, Page } from 'react-pdf/dist/esm/entry.vite'

이렇게만 하면 아래 링크들에 있는 에러가 발생

https://stackoverflow.com/questions/45363156/error-unknown-action-from-worker-readerheadersready-when-loading-a-pdf-using-p

https://github.com/wojtekmaj/react-pdf/issues/1232

pdfjs 라이브러리의 버전이 맞지 않아서 발생하는 것으로 보임

node_modules 에서 찾아서 캡쳐한 모습

그래서 pdfjs.version 를 console로 찍어봤을때 나오는 버전을 설치하도록 강제해야 함

package.json 의 resolutions 필드에 pdfjs-dist 추가

"resolutions": {
    "pdfjs-dist": "2.16.105"
},

https://github.com/ealush/emoji-picker-react/issues/202

export default defineConfig({
  define: { global: 'window' },
}

 

require 구문 사용이 안됨. 플러그인 설치 필요

아니면 import 구문으로 변경해주면 된다.

 

브라우저 앱이 localhost 가 아니라 127.0.0.1 로 나타나는 문제

나의 경우, 백엔드 서버 쪽에서 CORS 설정이 localhost 라는 이름으로 되어있어서 꼭 해주어야 했다.

// vite.config.js
import { defineConfig } from 'vite'
import dns from 'dns'

dns.setDefaultResultOrder('verbatim')

export default defineConfig({
  // omit
})

https://github.com/vitejs/vite/issues/9195

https://vitejs.dev/config/server-options.html#server-host

 

 

 

참고

반응형