Vite 설치하기 - 공식문서 확인
Vite를 설치하고 구성하는 과정은 Vite의 공식 문서에 자세히 설명되어 있습니다. Vite 설치는 간단하지만, 몇 가지 주의할 점이 있으며, 이는 Vite의 특징적인 방식과 관련이 있습니다. Vite 설치 과정 및 주의사항 그리고 설치 중 발생한 문제에 대해 공유하려고 합니다.
설치 시 주의사항 및 Vite만의 특징:
- ESNext 변환: Vite는 최신 JavaScript 문법을 사용하며, esnext를 대상으로 코드를 변환합니다.
- 네이티브 ES Module: Vite는 네이티브 ES 모듈을 기반으로 작동하므로, 브라우저에서 직접 모듈을 로드할 수 있습니다.
- 동적 임포트 및 import.meta 사용: Vite는 네이티브 ESM 동적 임포트를 지원하며, import.meta 구문을 사용하여 모듈에 대한 메타데이터에 접근할 수 있습니다.
- index.html 위치: Vite에서는 index.html 파일을 프로젝트의 루트 디렉토리에 위치시킵니다. 이는 기존 CRA 프로젝트와 다른 점입니다.
- URL 자동 맞춤: Vite는 index.html 내의 URL을 자동으로 처리하므로, %PUBLIC_URL%과 같은 Placeholder를 사용할 필요가 없습니다.
기술 스택 체크
- React, Typescript, Vite
프로젝트를 처음부터 시작한다고 하면, 다음과 같이 적용하면된다.
$ npm create vite@latest
하지만, 나는 기존에 프로젝트에서 Craco 에서 Vite로만 변경하는것이기 때문에 다르게 접근해야된다.
vite 설치하기
npm install vite
vitejs/plugin-react-swc 플러그인을 설치
npm install @vitejs/plugin-react-swc
vite설치를 하면서 찾아본것중에 plugin-react-swc라는 것이 있었다. swc가 무엇일까 생각을 하면서 swc에 대해서 찾아봤다.
SWC?
SWC(Speedy Web Complier)는 Rust로 작성된 고성능 컴파일러입니다. JavaScript, TypeScript, JSX 등의 코드를 빠르게 컴파일하고 최적화할 수 있는 도구로, 웹 개발자들 사이에서 점차 인기를 얻고 있습니다. SWC의 주요 목적은 Babel과 같은 기존 컴파일러보다 훨씬 빠른 컴파일 속도를 제공하는 것입니다.
SWC는 단일 스레드에서는 Babel보다 20배 빠르고 4개 코어에서는 70배 빠릅니다.
-https://swc.rs/
SWC의 주요 특징:
- 고성능: Rust의 효율적인 메모리 관리와 성능을 활용하여 JavaScript 코드를 빠르게 파싱하고 컴파일합니다.
- 다양한 언어 지원: JavaScript, TypeScript, JSX 등 다양한 웹 기술을 지원합니다.
- 플러그인 시스템: Babel과 유사한 플러그인 기반 아키텍처를 갖추고 있어, 사용자가 필요에 따라 기능을 추가할 수 있습니다.
- 최적화된 코드 생성: 코드의 크기와 실행 시간을 최적화하기 위한 다양한 기술을 적용합니다.
SWC 사용 이유:
- 속도 향상: 기존 JavaScript 컴파일러보다 몇 배 빠른 속도로 컴파일할 수 있어, 큰 프로젝트나 복잡한 빌드 파이프라인에서 개발 효율성을 크게 향상시킵니다.
- 용이한 통합: 다른 빌드 도구나 프레임워크와 쉽게 통합될 수 있어, 현대적인 웹 개발 환경에 잘 맞습니다.
SWC는 특히 Vite, Next.js와 같은 현대적인 프론트엔드 도구와 함께 사용될 때 그 장점이 크게 부각됩니다. 이러한 시스템에서 SWC를 사용하면 빌드 시간을 단축시키고, 개발자 경험을 향상시킬 수 있습니다.
Vite에서는 이러한 swc를 제공하고 있었기 때문에 더 빠른 컴파일러를 사용하기 위해 설치했다.
Vite 설치중에 발생한 의존성 문제

우리가 설치하려는 도구는 Vite와 @vitejs/plugin-react-swc입니다. 설치 중 'ERR' 메시지가 나타난다면, 이 메시지의 내용을 주의 깊게 살펴볼 필요가 있습니다. 이러한 오류 메시지는 발생한 문제의 원인과 상황을 설명하며, 해결을 위해 어떤 조치를 취해야 하는지 구체적인 지침을 제공합니다. 따라서 문제 해결을 위해서는 오류 메시지를 자세히 읽고, 그 안내에 따라 필요한 조치를 취하는 것이 중요합니다.
원인파악.

저는 다음과 같은 이유를 찾을 수 있었습니다. 내가 사용하고 있는 @types/node 버전은
@types/node": "^17.0.45"
사용하고 있었지만, vite@5.2.6 버전에서는 @type/node 버전을 18.0.0 이상 버전이나 20.0.0 이상 버전을 원했었다.

기존에 우리가 사용하는 @type/node는 17.0.45 버전을 사용하기 때문에 다음과 같은 문제가 발생한것을 알 수 있었고,
해당버전을 update함으로 써 문제를 해결할 수 있었다.
dependencies / devDependencies 구분하기
dependencies는 실제 프로덕션 환경에서 애플리케이션이 실행될 때 필요한 라이브러리나 프레임워크를 포함합니다. 이는 앱이 사용자에게 서비스를 제공하는 데 직접적으로 필요한 코드입니다. 반면, devDependencies는 개발 과정에서만 사용되며, 실제 운영 환경에서는 필요하지 않은 도구들을 포함합니다.
이 구분을 통해 프로덕션 빌드의 크기를 최소화하고, 필요하지 않은 코드가 배포되지 않도록 하여 보안과 성능을 향상시키며, 프로젝트의 유지보수를 용이하게 한다고 한다.
기존에 devpendencies에 있던 type, testing 관련 내용은 실제 운영 환경에는 필요하지 않지 않기 때문에 dev로 변경해줬습니다. :)

Craco와 관련된 라이브러리 삭제하기
vite 설치를 완료했다면, Craco와 관련된 라이브러리들을 삭제하면 됩니다.
svgr/webpack 같은 경우, vite에서 제공하는 plugin이 있기때문에 필요없다고 생각해서 같이 삭제를 했습니다.
- "@craco/craco" : "^7.1.0"
- "react-scripts" : "^5.0.1"
- "@svgr/webpack" : "^8.1.0" (vite 내장 라이브러리 사용예정)
Vite 필수 환경 적용하기
index.html 그리고 프로젝트의 루트
공식문서을 보면, index.html 파일에 대해서 내용이 적혀있습니다. 기존에 사용하는 방식과는 다르게 파일의 위치와 처리방식에 대해 중요한 변경사항이 존재합니다.
- index.html 파일의 위치 변경: 기존에 많은 프로젝트에서 사용되던 public 폴더에서 프로젝트의 루트 디렉토리로 index.html 파일을 이동해야 합니다. 이는 Vite가 추가적인 번들링 과정 없이 index.html 파일을 애플리케이션의 진입점으로 직접 사용할 수 있게 하기 위함입니다.
- JavaScript 모듈 로딩: index.html에서 JavaScript 코드를 불러오기 위해 <script type="module" src="..."> 태그를 사용해야 합니다. 이는 현대 브라우저가 지원하는 ES 모듈을 통해 직접적으로 JavaScript 파일을 로드하는 방식입니다.
- URL 자동 맞춤: Vite는 index.html 내의 URL을 자동으로 처리합니다. 예를 들어, CRA에서 사용되었던 %PUBLIC_URL%과 같은 플레이스홀더를 사용할 필요가 없으며, 이러한 내용은 삭제해야 합니다. Vite는 필요한 URL을 자동으로 조정하여, 개발 및 배포 환경에서의 문제를 최소화합니다.
정리하자면,
- index.html 경로 변경 public -> Root
- %PUBLIC_URL% 삭제하기
//이전
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
//변경
<link rel="icon" href="/favicon.ico" />
- index.html body에 script추가하기
//이전
<body>
<nscript>You need to enable JavaScript to run this app.</nscript>
<div id="root"></div>
</body>
//이후
<body>
<nscript>You need to enable JavaScript to run this app.</nscript>
<div id="root"></div>
<script type="module" src="/src/index.tsx"></script>
</body>
명령줄 인터페이스
vite가 설치된 프로젝트는 vite 명령을 통해 바로 Vite를 실행할 수 있습니다. (npx vite을 이용해도 되구요.) 기본적으로 Vite에서 제공하는 npm 스크립트는 아래와 같습니다.
{
"scripts": {
"dev": "vite", // 개발 서버를 실행합니다. (`vite dev` 또는 `vite serve`로도 시작이 가능합니다.)
"build": "vite build", // 배포용 빌드 작업을 수행합니다.
"preview": "vite preview" // 로컬에서 배포용 빌드에 대한 프리뷰 서버를 실행합니다.
}
}
Vite.config.mts 추가하기
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc';
import tsconfigPaths from 'vite-tsconfig-paths';
import svgr from 'vite-plugin-svgr';
export default defineConfig({
plugins: [react(), tsconfigPaths(), svgr()],
server: {
port: 3000,
},
});
초기에 vite.config.ts 파일을 사용하여 Vite 설정을 진행했지만, Vite에서는 CommonJS(Node API) 사용을 중단하고 ECMAScript Modules(ESM)을 채택했습니다. 이에 따라 설정 파일을 vite.config.mts로 변경하여 ESM 방식을 따르게 되었습니다. 변경 과정에서는 다음과 같은 사항들이 포함되었습니다:
- 파일 확장자 변경: vite.config.ts에서 vite.config.mts로 파일 확장자를 변경하여, Vite의 ESM 빌드를 사용하도록 설정했습니다.
- 필요한 플러그인 추가: 프로젝트에서 TypeScript 설정 경로를 해석하고 SVGR을 사용하기 위해 vite-tsconfig-paths와 vite-plugin-svgr를 import하여 설정 파일에 추가했습니다.
이러한 변경을 통해 Vite 설정이 최신 모듈 시스템을 준수하면서, 개발 환경이 더욱 최적화되었습니다. 이는 프로젝트의 구성과 유지 관리에 있어 효율성을 높이는 데 기여합니다.
CJS Node API 사용 중단
Vite의 CJS Node API는 더 이상 제공되지 않습니다. require('vite') 호출 시 경고가 나타나며, 이 대신 파일이나 프레임워크를 업데이트하여 Vite의 ESM 빌드를 가져오도록 해야 합니다.
표준 Vite 프로젝트에서 다음을 확인해 주세요:
1. vite.config.js 파일에서 ESM 문법을 사용하고 있습니다.
2. 가장 가까운 package.json 파일에 "type": "module"이 있거나 .mjs/.mts 확장자(예: vite.config.mjs 또는 vite.config.mts)를 사용하고 있습니다.
다른 프로젝트의 경우, 몇 가지 일반적인 접근 방식이 있습니다:
ESM을 기본값으로 설정하고, 필요한 경우 CJS를 사용: 프로젝트
package.json에 "type": "module"을 추가하세요.
이후 모든 *.js 파일은 ESM으로 해석되며 ESM 문법을 사용해야 합니다. 다만 확장자가 .cjs인 파일은 CJS로 해석됩니다.
CJS를 기본값으로 유지하고, 필요한 경우 ESM을 사용: 프로젝트
package.json에 "type": "module"이 없다면, 모든 *.js 파일은 CJS로 해석됩니다. 다만 확장자가 .mjs인 파일은 ESM으로 해석됩니다.
Vite를 동적으로 임포트: CJS를 계속 사용해야 하는 경우, import('vite')를 사용하여 Vite를 동적으로 임포트할 수 있습니다. 이를 위해 코드가 async 컨텍스트에서 작성되어야 하지만, Vite의 API가 대부분 비동기적이기 때문에 일반적으로 문제가 되지 않습니다.
자세한 내용은 트러블슈팅 가이드를 참조하세요.
Reference : https://ko.vitejs.dev/guide/migration.html
tsconfig.json 변경하기
공식문서 v4에서 마이그레이션하기를 살펴보면, Typescript를 사용하면다면, Rollup 4에서 요구하는 것과 같다.
moduleResolution: 'bundler'(또는 node16/nodenext)를 설정해 주세요. 또는 skipLibCheck: true를 설정할 수도 있습니다.
"bundler" 모듈 해석 방식은 TypeScript 5버전부터 지원되며, 외부 번들러로 번들링될 코드에 대해 보다 유연한 모듈 해석을 지원합니다. 이 옵션은 TypeScript 컴파일러에게 해당 코드가 번들러에 의해 처리될 것이므로 모듈 해석 규칙을 너무 엄격하게 적용하지 말라는 의미입다.
Vite는 기본적으로 Rollup을 사용하여 번들링을 수행하므로, TypeScript 컴파일러에게 해당 프로젝트는 번들러에 의해 처리될 것이라고 전달하기 위해 "bundler" 모듈 해석 방식을 기본값으로 설정하는 것이 타당합니다. 이렇게 함으로써 TypeScript 컴파일러가 더 유연하게 모듈을 해석하고 번들러에게 필요한 정보를 제공할 수 있습니다.
Vite는 번들링에 특화된 도구이므로 해당 프로젝트에 대해 번들링 관련 설정을 적용하여 좀 더 효율적인 빌드를 할 수 있도록 도와줍니다.
reference : Chat gpt-3.5
- moduleResolution "node" -> "bundler" 변경
//이전
{
"compilerOptions": {
"target": "es6",
"lib": ["dom", "dom.iterable", "esnext"],
"typeRoots": ["src/types"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
// "strict": true,
"forceConsistentCasingInFileNames": false, // 컴파일러가 파일 이름의 대소문자를 구분하지 않도록 함
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src", "tailwind.config.js", "craco.config.js"],
"extends": "./tsconfig.paths.json"
}
{
"compilerOptions": {
"target": "esnext",
"lib": ["dom", "dom.iterable", "esnext"],
"typeRoots": ["src/types"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"types": ["vite/client", "vitest/globals", "@testing-library/jest-dom"]
},
"include": ["src"],
"extends": "./tsconfig.paths.json"
}
Vite/Client trobble shotting

Client Types 변경하기
src/react-app-env.d.ts -> vite-env.d.ts
//전
// src/react-env.d.ts
/// <reference types="react-scripts" />
//후
// src/vite-env.d.ts
/// <reference types="vite/client" />
/// <reference types="vite-plugin-svgr/client" />
에러 확인 moduleResolution : "bundler"

Vite로 전환하면서 겪은 어려움 중 하나는 moduleResolution: "bundler" 설정과 관련된 TypeScript의 버전 문제였습니다. 이 설정은 TypeScript 5.0 이상에서 제공되므로, 이전 버전에서는 사용할 수 없었습니다. 이에 대한 문제를 해결하기 위해 다음과 같은 조치를 취했습니다:
- TypeScript 버전 확인 및 업데이트: 현재 프로젝트에서 사용 중인 TypeScript의 버전을 확인하고, TypeScript 5.0 이상으로 업데이트하여 moduleResolution: "bundler" 옵션을 사용할 수 있도록 했습니다. 이를 위해 package.json 파일에서 TypeScript의 버전을 "^4.9.5"에서 "^5.4.3"으로 변경했습니다.
- 환경 설정 검토: Visual Studio Code 버전 1.76.2와 TypeScript 5.0.2 버전을 사용하여 호환성을 확인하고, 새로운 설정이 정상적으로 작동하는지 검증했습니다.
이러한 업데이트를 통해 Vite 프로젝트에서의 설정 문제를 해결하고, 최신 TypeScript 기능을 활용할 수 있게 되었습니다.
Parsing error : EsLint was configured to run on `<tsconfigRootDir>/vite.config.ts`

다음과 같은 문제를 해결하기 위해서 구글 서칭을 진행했고, 다음과 같이 해결했다는 방법을 통해서 문제를 해결했다.


"ignorePatterns": ["node_modules/", "vite.config.ts", ".eslintrc.json"],
Build Error 잡기

settting을 맞추고 나니, 빌드에서 발생한 오류들이 참 많았다. 간단한 오류말고 vite로 변경했을때 발생하는 오류들은 따로 정리를 해봤다.
1. process.env 수정하기
//이전
const BASE_URL = `${process.env.REACT_APP_SERVER}`;
//변경
const BASE_URL = `${import.meta.env.VITE_SERVER}`;
env 수정하기
REACT_APP_SERVER -> VITE_SERVER
tailwind css 적용하기
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
중첩 관련 플로그인 설치
npm install -D postcss-nesting
module.exports = {
plugins: {
'postcss-import': {},
'tailwindcss/nesting': 'postcss-nesting',
tailwindcss: {},
autoprefixer: {},
}
}
비교


빌드속도 : 9.047s -> 3.53s 로 3배가량 개선
(근데, 성능개선 할 부분이 빌드에서 부터 너무 잘보여서 부끄럽다.)
정리
vite로 마이그레이션을 정리하기 위해서 마이그레이션을 5번정도 해본거같다. 한번한번 해보면서 trobble shotting에 대해서 정리하고 이해할 수 있었고, vite로 바꾸는 이유에 대해서 공부할 수 있었다.
레퍼런스
https://tailwindcss.com/docs/using-with-preprocessors
Using with Preprocessors - Tailwind CSS
A guide to using Tailwind with common CSS preprocessors like Sass, Less, and Stylus.
tailwindcss.com
https://github.com/vitejs/vite/issues/13747
ESLint was configured to run on `<tsconfigRootDir>/.eslintrc.cjs` using `parserOptions.project` · Issue #13747 · vitejs/vite
Describe the bug With React+Typescript template ESLint is configured to run on /.eslintrc.cjs but tsconfig is not configured to run on /.eslintrc.cjs. Reproduction https://github.com/xixixao/repro-...
github.com
https://stackoverflow.com/questions/75870063/vscode-and-typescript-5-moduleresolution-bundler
VSCode and Typescript 5 moduleResolution "bundler"
I'm trying to use typescript 5.0.2 and vscode 1.76.2 with the new moduleResolution "bundler" setting in tsconfig. I'm building a frontend with vite so typescript is only being used for
stackoverflow.com
https://github.com/vuejs/tsconfig/issues/8
Adopt TypeScript 5+ `"moduleResolution": "bundler"` · Issue #8 · vuejs/tsconfig
Adopt TypeScript 5+ "moduleResolution": "bundler". This should result in more correct module resolution for Vite projects that use this config. We should also any other props https://www.typescript...
github.com
https://dev.to/ayc0/typescript-50-new-mode-bundler-esm-1jic
TypeScript 5.0: new mode bundler & ESM
In TypeScript 5.0, 2 new features were released: moduleResolution:...
dev.to
Vite
Vite, 차세대 프런트엔드 개발 툴
ko.vitejs.dev
https://github.com/vitejs/vite-plugin-react-swc
GitHub - vitejs/vite-plugin-react-swc: Speed up your Vite dev server with SWC
Speed up your Vite dev server with SWC. Contribute to vitejs/vite-plugin-react-swc development by creating an account on GitHub.
github.com