본문 바로가기
FE/vite

vite의 module 처리와 typescript 설정 살펴보기

by livemehere 2023. 1. 9.

NPM Dependency 설치 및 Pre-Bundling

브라우저에서도 es module system 을지원하고 있고, vite는 이방식을 사용하고 있습니다.

하지만 아래 코드와같이 브라우저 상에서는 npm 모듈을 임포트할 수 없습니다.

node 환경이 아니기 때문에 인식조차 할 수 없기 때문입니다

예시로 dayjs 라이브러리를 루트dir에서 설치하고 브라우저에서 import 해본 결과입니다.

import dayjs from 'dayjs'

console.log(dayjs)

 

 

왼쪽은 vite dev 결과이고, 오른쪽은 html파일을 그대로 열었을 때 입니다.

 

 

이는 vite 가해주는 역할 덕분입니다.

1. 설치된 commonJS/UMD 모듈을 ESM으로 변경합니다.

2. esbuild를 사용하여 변환한 모듈들을 pre-bundling 하여 브라우저에 내장합니다.

3. 매번 cold start를 하여 빠르게 번들링한 결과를 제공합니다.

 

확인해보기

http://127.0.0.1:5173/node_modules/dayjs/dayjs.min.js

node_modules 의 경로의 모듈을 모두 esbuild로 번들링한다음 브라우저에 내장

한번 번들링된 모듈은 http header에 의해서 캐시되기 때문에, 지우고 싶다면 --force 옵션을 함께 주어 삭제할 수 있습니다.

Hot Module Replacement

개발환경에 필수적인 HMR을 내장하고 있습니다.

별도의 설정 없이 기본적으로 설정되어있습니다.

Typescript

vite는 기본적으로 .ts 를 지원하고 있습니다.

하지만 트렌스컴파일링만 해줄 뿐 타입체크는 해주지 않습니다(tsconfig 를 직접 설정해야 합니다)

 

.ts 로변경 예시

import * as dayjs from 'dayjs'

console.log(dayjs)

function hello(a){
    return a;
}

hello('helo');

추가적으로 tsconfig.json 을 설정해야하는데 몇가지 주의사항이 있습니다.

tsconfig Compiler Option

1. esModuleInterop: true

이항목은 해주는 것이 좋습니다.

사용하는 모듈은 대부분 commonJS 시스템으로 작성되었기 때문에, 이를 ESM 으로 트랜스컴파일링하는 과정에서 ESM표준에 맞지 않게 변환 되면 에러를 반환합니다.

 

import a from 'a' 일때, a는 반드시 object 여야합니다.

commonJS -> ESM 으로 변환될 때 위와 같은 문법은 const XXX = require("XXX").default 로 변환되기 때문에

a가 만약 callable 한 형태라면 .default 라는 프로퍼티가 없을 수 있기 때문에 에러를 반환합니다.

 

commonJS 모듈이 아래와같이 default 프로퍼티를 가지고 있어야 에러가 발생하지 않습니다.

var foo = exports.foo = 42;
exports.default = 21; 

 

이때, esModuleInterop를 true 로 설정하면 만약 default 프로퍼티가 없는 commonJS 모듈은 아래와 같이

const XXX = __importDefault(require("XXX')).default

모듈 전체를 다시 감싸서 default 프로퍼티를 생성해줌으로써 default import 가 언제나 가능하도록 해줍니다.

 

2. isolatedModules: true

이 항목은 필수 입니다.

esbuild 는 typescript를 결국 javascript 로 트렌스컴파일링 하는데, enum, type-only import 는 javascript 스펙이 아니기 때문에 모두 사라지게 됩니다.

그렇기 때문에 명시적으로 export, import 해서 사용하도록 유도하여야 합니다.

 

vue 의경우 이 옵션이 잘동작하지 않는 버그가 있는데, skipLibCheck:true 를 현재까지는 해주어야 합니다.

 

3.useDefineForClassFields:true

이 항목도 필수 입니다.

ESM의 표준이기 때문입니다.

 

 

반응형