본문 바로가기
Web Study/React 관련

Vite 공식 문서 - 기본 설정하기

by 쿠리의일상 2023. 6. 20.

https://ko.vitejs.dev/guide/features.html

 

Vite

Vite, 차세대 프런트엔드 개발 툴

ko.vitejs.dev

한글화 해주신 분이 누군지 모르겠지만 공식 문서가 정말 깔끔하게 잘 되어있다. 감사합니다...!

CRA 만 사용하다가 Vite 를 쓰니 아직은 차이가 클 정도로 큰 프로젝트를 한 적은 없어서 체감은 안되지만,

빠르다고 명성이 자자한 Vite, 공식 문서를 차근히 읽어나가며 공부해보기로 한다.

기존의 CRA 와 Vite 를 비교한 것은 바로 전의 글로 정리했다.

 

Vite 가 지원하는 기능

HMR

기본적으로 ESM 을 통하여 HMR API 를 제공한다. HMR, Hot Module Replacement 로 페이지를 다시 로드하거나 애플리케이션 상태를 날려버리지 않고 즉각적이고 정확한 업데이트를 제공할 수 있다.

 

Vite Typescript

ts 파일에 대해 트랜스파일링만 수행하여 타입 검사는 IDE 와 빌드 프로세스에서 수행된다.

Vite 변환 과정에서 타입 검사를 수행하지 않는 이유는 먼저, 두 작업이 기본적으로 다르기 때문이다. 

트랜스파일링은 파일 단위로 작동

타입 검사는 전체 모듈 그래프에 대한 탐색이 필요

그래서 Vite 의 변환 파이프 라인에 타입 검사를 추가하게 되면 속도 이점이 사라질 수 있는 것이다.

기본적으로 Vite의 역할은 소스 모듈을 가능한 빠르게 브라우저에서 실행할 수 있는 형태로 변환하는 것이므로 Vite 의 변환 파이프 라인에서 정적 분석 검사를 분리하는 것을 권장한다고 한다.

Typescript 트랜스파일링은 EsBuild 를 이용하며 tsc 에 비해 20~30배 빠른 퍼포먼스를 보인다고 한다!

 

타입스크립트 컴파일러 옵션

tsconfig.json 파일 내 compilerOptions 설정

  • "islatedModules" : true 
    • esbuild 는 타입에 대한 정보 없이 변환(트랜스파일링)만 수행하게끔 설정
    • 혹시 해당 설정으로 마이그레이션이 불가능하다면 rollup-plugin-friendlt-type-imports 와 같은 써드파티 플러그인을 사용하는 방법도 있다.
  • 혹여 특정 라이브러리에서 위 설정 때문에 타입 체크가 정상적으로 동작하지 않는다면 해당 모듈이 이슈를 수정할 때까지 "skipLibCheck" : true 를 사용해준다.
  • "useDefineForClassFields" : true 
    • tsc 버전 4.3.2 이상, ECMAScript 표준을 따르도록 하는 설정
    • 클래스의 필드에 크게 의존하는 라이브러리를 사용하는 경우라면 라이브러리를 사용하는 것에 대한 옵션을 수정하는 경우 주의가 필요
    • lit-element 등의 라이브러리는 false 로 설정해준다.
  • 그외 빌드 결과에 영향을 미치는 옵션들은 : extends, importsNotUsedAsValues, preserveValueImports, jsxFactory, jsxFragmentFactory ...

 

Client Types

Vite는 기본적으로 Nodejs API 기반의 타입 시스템을 차용하고 있으며 클라이언트의 환경을 구성하고자하면 d.ts 선언 파일을 추가한다.

// d.ts
<reference types="vite/client" />

 

또는 tsconfig.json 내에 compilerOptions.types 옵션에 vite/client 를 명시해준다.

{
	"compilerOptions": {
    	"types": ["vite/client"]
    }
}
  • .svg 와 같은 에셋이 제공
  • Vite 를 통해 주입되는 import.meta.env 에 명시된 환경 변수 타입 제공
  • import.meta.hot에 명시된 HMR API 타입들 제공

 

JSX 가능

esbuild 를 이용하여 컴파일링 수행

vite.config.js 파일에서 esbuild 옵션을 추가하여 커스터마이징도 가능하다.

// vite.config.js
export default defineConfig({
  esbuild: {
    jsxFactory: 'h',
    jsxFragment: 'Fragment'
  }
})

 

CSS의 모듈화

.module.css 로 끝나는 css 파일은 모듈 파일로 취급되어 자바스크립트의 모듈처럼 import 하여 사용이 가능하다.

Vite는 모던 브라우저가 타깃이므로 네이티브css 를 사용하도록 권고하고 있으므로 scss, sass, less, styl, stylus 같은 css전처리기가 필요한 파일을 지원하지 않는다.

 

정적 Assets

정적인 에셋을 import 하는 경우 public url 이 반환이 기본이다.

import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl

url 쿼리를 사용하여 (?로) 어떻게 가져올 것인지 명시할 수 있다.

// String 타입으로 에셋 가져오기
import assetAsString from './shader.glsl?raw'

 

JSON 파일

json 파일은 바로 import 가 가능, 객체 형태로 가져오거나 필드를 { } 안에 넣어 원하는 필드만 가져올 수도 있음

 

Glob Import

import.meta.glob 함수를 사용하여 여러 모듈을 한번에 가져올 수 있도록 지원한다. 다만 변수나 표현식을 사용할 수 없고 리터럴값을 전달해야한다!

const modules = import.meta.glob('./dir/*.js')

 

Web Workers

웹 워커는 new Worker() 나 new SharedWorker() 를 통해 가져오는 것이 권장

const url = new URL('./worker.js', import.meta.url)
const worker = new Worker(url)


const url = new URL('./worker.js', import.meta.url)
const worker = new Worker(url, {
  type: 'module'
})

또는 쿼리 접미사인 ?worker 또는 ?sharedworker 를 붙여서 가져올 수도 있다.

import MyWorker from './worker?worker'

const worker = new MyWorker()

 

기본적으로 워커는 프로덕션 빌드 분리된 청크로 컴파일된다. 그러므로 Base64 포맷의 문자열로 사용하고자 한다면 inline 쿼리를 사용해준다.

 

Vite 의 빌드 최적화

css 코드의 분리

vite 는 비동기적으로 불러와지는 청크 내 CSS 코드가 포함된 경우 자동으로 추출하여 파일로 분리해준다. 해당 청크를 불러올 때 <link> 태그를 사용하여 분리된 css 를 불러오게하여 계산 후 청크를 렌더하도록 해준다.

해당 과정을 통해 CSS가 렌더링될 때 화면이 잠깐 반짝이는 FOUC 현상을 피할 수 있기에 복잡한 과정을 거치는 것이다.

굳이 이러한 설정이 필요없는 경우 build.cssCodeSplit 옵션의 값을  false 로 만들어서 비활성화 시킬 수 있다.

Preload Directives Generation

빌드 할 때 Direct import 구분에 대해 <link ref="modulepreload"> 디렉티브를 이용하여 미리 모듈을 캐싱하도록 자동 변환해준다. 그래서 해당 모듈을 필요할 때마다 바로 사용할 수 있게 된다.

Async Chunk Loading Optimization

빌드 시 Rollup은 공통 청크 파일을 생성하게 된다.

위와 같은 상황에서 Dynamic import 를 통하여 불러오는 경우 Entry -> A -> C 순서로, 비동기적으로 A 청크가 불러와지고 A가 모두 파싱된 후에야 C가 필요하다는 사실을 알게되기에 네트워크 왕복이 필요하게 된다.

그런데 Vite 에선 Preload 를 이용하여 A를 가져올 때 C청크를 병렬적으로 가져올 수 있도록 Dynamic import 구문을 자동으로 재작성해준다. Entry -> ( A + C )

Preload 하도록 하여 쓸데없이 낭비되는 네트워크 왕복을 줄이도록 구성한다.

 

기본 포맷팅 플러그인 설치

npm i --save-dev eslint eslint-config-prettier eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react prettier

ts 템플릿일 때 추가 설치

npm i --save-dev @typescript-eslint/eslint-plugin @typescript-eslint/parser

Vite ts 의 tsconfig.json 설정 참고용!

{
  "compilerOptions": {
    "types": ["node"],
    "target": "ESNext", // es버젼을 사용하겠다.
    "useDefineForClassFields": true, // class field를 사용하겠다.
    "lib": ["DOM", "DOM.Iterable", "ESNext"], // 사용할 라이브러리를 설정한다.
    "allowJs": false, // js를 사용하지 않겠다.
    "skipLibCheck": true, // 모든 선언 파일(*.d.ts)의 타입 검사를 건너뜁니다
    "esModuleInterop": false,
    // 런타임 바벨 생태계 호환성을 위한 __importStar와 __importDefault 헬퍼를 내보내고 타입 시스템 호환성을 위해 --allowSyntheticDefaultImports를 활성화합니다.
    "allowSyntheticDefaultImports": true, // default export가 없는 모듈에서 default imports를 허용합니다. 코드 방출에는 영향을 주지 않으며, 타입 검사만 수행합니다
    "strict": true, // strict mode에서 파싱하고 각 소스 파일에 대해 "use strict"를 내보냅니다.
    "forceConsistentCasingInFileNames": true, // 동일 파일 참조에 대해 일관성 없는 대소문자를 비활성화합니다.
    "module": "ESNext", // 모듈 코드 생성 지정: "ESNext"
    "moduleResolution": "Node", // 모듈 해석 방법 결정
    "resolveJsonModule": true, // .json 확장자로 import된 모듈을 포함합니다
    "isolatedModules": true, // 추가 검사를 수행하여 별도의 컴파일 (예를 들어 트랜스파일된 모듈 혹은 @babel/plugin-transform-typescript) 이 안전한지 확인합니다.
    "noEmit": true,
    "jsx": "react-jsx",
    "baseUrl": ".", // baseUrl을 기준으로 관련된 위치에 모듈 이름의 경로 매핑 목록을 나열합니다.
    "paths": {
      "@src/*": [
        //@src로 시작하면 아래 줄의 디렉토리를 의미한다.
        "src/*" //baseUrl을 기준으로 src/ 하위 디렉토리를 @src로 표현한다.
      ],
      "@components/*": ["src/components/*"] //@components로 시작하면 components/ 하위 디렉토리를 의미한다.
    }
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

 

절대 경로에 필요한 node types 설치

npm i -D vite-tsconfig-paths @types/node

vite.config.ts 에 절대경로  수동으로 설정하기

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tsconfigPaths from 'vite-tsconfig-paths';
import { resolve } from 'path';

// https://vitejs.dev/config/
export default defineConfig({
  resolve: {
    alias: [
      { find: '@src', replacement: resolve(__dirname, 'src') },
      {
        find: '@components',
        replacement: resolve(__dirname, 'src/components'),
      },
    ],
  },

  plugins: [react(), tsconfigPaths()],
});

위에 지정했던 과정이 귀찮다... 그럼 절대경로를 편하게 지정하고 싶다면 vite-tsconfig-paths 모듈을 사용하면 된다.

 

설정 파일 추가하기

.eslintrc.js

module.exports = {
  extends: [
    // By extending from a plugin config, we can get recommended rules without having to add them manually.
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:import/recommended',
    'plugin:jsx-a11y/recommended',
    // This disables the formatting rules in ESLint that Prettier is going to be responsible for handling.
    // Make sure it's always the last config, so it gets the chance to override other configs.
    'eslint-config-prettier',
  ],
  settings: {
    react: {
      // Tells eslint-plugin-react to automatically detect the version of React to use.
      version: 'detect',
    },
    // Tells eslint how to resolve imports
    'import/resolver': {
      node: {
        paths: ['src'],
        extensions: ['.js', '.jsx', '.ts', '.tsx'],
      },
    },
  },
  rules: {
    // Add your own rules here to override ones from the extended configs.
  },
};

.prettierrc

{
  "semi": false,
  "trailingComma": "all",
  "singleQuote": true,
  "printWidth": 200,
  "endOfLine": "auto"
}

 

이런 형태로 폴더 구성이 된다.

public 폴더

개발 시에 '/' 경로에, 배포 시에는 dist 폴더에 위치하게 된다.

public 폴더에 위치한 에셋을 가져오고자 하는 경우 항상 루트 기준으로 하는 절대 경로로 가져와야 함

 

'Web Study > React 관련' 카테고리의 다른 글

Custom Hooks  (0) 2023.07.21
React 컴포넌트 설계에 대해..  (0) 2023.07.18
Vite - 플러그인 사용하기  (0) 2023.06.19
CRA 와 Vite  (0) 2023.06.19
노마드코더 React Hooks - 2  (4) 2023.06.13