Programming language/vuejs

[vite] 지원하는 기능들

hello-world 2023. 2. 13. 16:16
728x90
반응형

지원하는 기능들

Hot Module Replacement

vite는 기본적으로 ESM를 통해 HMR API를 제공합니다. HMR 기능이 있는 프레임워크는 API를 활용하여 페이지를 다시 로드하거나 애플리케이션 상태를 날려버리지 않고 즉각적이고 정확한 업데이트를 제공할 수 있습니다. vite는 Vue Single File Components, React Fast Refresh 또는 @prefresh/vite과 같은 First-party HMR* 모듈을 제공하고 있습니다. (* Vite에서 직접 제공하는 HMR 모듈)

물론, create-vite에서 제공하는 템플릿 안에는 HMR 모듈이 포함되어 있기 때문에 굳이 위와 같은 방법을 따르지 않아도 됩니다.

TypeScript

vite는 .ts 파일에 대한 컴파일링 및 Import 역시 지원합니다.

단, 타입 체킹은 오로지 IDE 또는 빌드 프로세스에만 의존하며, Vite 자체에서는 .ts 파일에 대한 타입 체킹 작업을 진행하지 않습니다. 타입 체킹이 필요하다면 tsc --noEmit*을 빌드 스크립트에 넣어주세요. 만약 *.vue 소스 코드를 작성중이라면, vue-tsc를 설치해 vue-tsc --noEmit을 빌드 스크립트에 넣어서 타입 체킹을 하도록 설정할 수 있습니다. (* --noEmit: 컴파일링 없이 타입 체킹만을 수행하는 옵션)

Vite의 TypeScript 컴파일링은 Esbuild를 이용하며, TypeScript 소스 코드를 JavaScript 소스 코드로 변환하는 작업에 대해 tsc 대비 약 20~30배 정도 빠른 퍼포먼스를 보이고 있습니다. (HMR은 50ms 미만)

참고로 타입만을 가져오는 경우 잘못 번들링이 될 수 있으며, 이는 타입 전용 Imports와 Exports를 사용하여 이 문제를 우회할 수 있습니다:

import type { T } from 'only/types'
export type { T }

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

tsconfig.json 파일 내 compilerOptions 설정들의 값을 조작할 때는 특별한 주의가 필요합니다.

isolatedModules: true로 설정해주세요.

esbuild는 타입에 대한 정보 없이 변환(Transpilation)만을 수행하기에, const enum 또는 암시적으로 타입만을 가져오는 것과 같은 특정 기능을 지원하지 않습니다. 이를 감지하기 위해 tsconfig.json  compilerOptions 설정을 "isolatedModules": true와 같이 설정해줘야만 하며, 이 설정으로 TS가 위와 같은 상황에서 작동하지 않는 기능들에 대해 경고할 수 있게 됩니다.

그러나 vue와 같은 일부 라이브러리는 "isolatedModules": true로 설정할 경우 타입 체크가 정상적으로 동작하지 않습니다. 이러한 경우에는 해당 모듈이 이슈를 수정할 때 까지 "skipLibCheck": true를 사용해 오류가 발생되지 않도록 해주세요.

useDefineForClassFields

Vite 2.5.0 부터는 TypeScript의 변환 대상이 ESNext 또는 ES2022 이상인 경우, 기본 값을 true로 설정합니다. 이는 tsc 버전 4.3.2 이상 및 ECMAScript 표준을 따르도록 하는 설정입니다.

그러나 다른 프로그래밍 언어나 이전 버전의 TypeScript를 사용하던 사람들에게는 직관적이지 않은 내용일 수 있습니다. 이에 대한 자세한 정보는 TypeScript 3.7 릴리스 노트를 참고할 수 있습니다.

또한, MobX Vue 클래스 컴포넌트 8.X와 같은 대부분의 라이브러리는 "useDefineForClassFields": true인 것으로 가정하고 동작합니다. 따라서 만약 클래스의 필드에 크게 의존하는 라이브러리를 사용하는 경우라면, 이러한 라이브러리를 사용하는 것에 대해 옵션을 수정하는 경우 상당한 주의를 기울어야 합니다.

다만 lit-element를 포함해 일부 라이브러리는 아직 이 새로운 기본값이 적용되지 않았습니다. 이러한 경우에는 useDefineForClassFields의 값을 false로 설정해주세요.

빌드 결과에 영향을 미치는 또 다른 컴파일러 옵션들

다만 "isolatedModules": true로 마이그레이션 할 수 없다면, rollup-plugin-friendly-type-imports와 같은 써드 파티 플러그인을 사용하는 방법도 있습니다. 그러나 이러한 접근 방식은 Vite에서 공식적으로 지원하는 방법은 아닙니다.

Client Types

vite는 기본적으로 Node.js API 기반의 타입 시스템을 차용하고 있습니다. 따라서 Client-side의 환경을 위해 Shim을 구성하고자 한다면, d.ts 선언 파일을 추가해주세요.

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

또는, tsconfig  compilerOptions.types 옵션에 vite/client를 명시해 줄 수도 있습니다.

이를 통해 다음에 대한 Shim이 제공됩니다.

  • .svg와 같은 에셋
  • Vite를 통해 주입되는 import.meta.env에 명시된 환경 변수 타입들
  • import.meta.hot에 명시된 HMR API 타입들

TIP

타입을 재정의하고자 한다면 트리플-슬래시 지시자(Triple-slash Reference) 앞에 선언해주세요. 가령, *.svg의 default import를 React 컴포넌트로 만들고자 한다면 아래와 같이 타입을 재정의할 수 있습니다:

declare module '*.svg' {
  const content: React.FC<React.SVGProps<SVGElement>>
  export default content
}

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

Vue

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

CSS

.css 파일을 Import 할 때, 기본적으로 HMR을 위해 <style> 태그로 변환되어 불러와지게 됩니다. 물론 String 타입의 모듈로 가져올 수도 있구요.

import style from './style.css'

console.log(style) // 정의한 CSS를 문자열로 가져옵니다.

CSS @import 그리고 URL 재정의(Rebasing)

vite는 postcss-import를 이용해 CSS의 @import를 처리합니다. 또한, CSS url()로 참조되는 모든 리소스들(다른 디렉터리에 존재한다 해도)에 대해 별다른 설정 없이 자동으로 Base를 맞추어주는 재정의(Rebasing) 작업 역시 진행해주고 말이죠.

별칭을 이용한 @import도 지원하며, URL 재정의나 별칭은 CSS 말고도 Sass와 Less에서도 사용이 가능합니다.

PostCSS

만약 프로젝트에 PostCSS 설정 파일이 존재한다면, vite는 이를 이용해 모든 CSS 파일에 해당 설정을 적용합니다.

참고로 CSS의 최소화는 PostCSS 이후에 진행되며, build.cssTarget 옵션을 이용해 설정할 수 있습니다.

CSS Modules

.module.css 확장자로 끝나는 모든 CSS 파일들은 CSS 모듈 파일로 취급되며, 일반적인 JavaScript 모듈처럼 사용이 가능합니다.

/* example.module.css */
.red {
  color: red;
}
import classes from './example.module.css'
document.getElementById('foo').className = classes.red

참고로, CSS 모듈에 대한 동작 방식을 입맛대로 수정할 수 있습니다. css.modules 옵션 옵션을 참고해주세요.

가령 css.modules.localsConvention 옵션을 camelCase로 설정하게 되면(localsConvention: 'camelCaseOnly'), 아래와 같이 가져올 수 있게 됩니다.

// .apply-color -> applyColor
import { applyColor } from './example.module.css'
document.getElementById('foo').className = applyColor

CSS Pre-processors

vite는 모던 브라우저만을 타깃으로 하기에, 표준을 준수하도록 postcss-nesting과 같은 CSSWG 초안을 구현한 PostCSS 플러그인과 함께 네이티브 CSS 변수를 사용하도록 권고하고 있습니다.

다시 말해, vite는 기본적으로 .scss, .sass, .less, .styl, .stylus와 CSS 전처리기가 필요한 파일을 지원하지 않습니다. 다만 필요한 경우 어렵지 않게 설치해 바로 사용할 수 있습니다.

# .scss 그리고 .sass
npm add -D sass

# .less
npm add -D less

# .styl 그리고 .stylus
npm add -D stylus

Vue 싱글 파일 컴포넌트를 사용하는 경우, 설치 후 별 다른 설정 없이도 <style lang="sass">와 같은 CSS 전처리기를 바로 사용할 수 있습니다. Sass나 Less에서의 @import 별칭 또한 Vite에서 사용이 가능합니다. url()로 참조되는 파일들 역시 자동으로 올바른 URL을 갖도록 재정의되고 말이죠.

다만 Stylus의 경우 API 충돌로 인해 Vite의 @import 별칭과 URL 재정의 기능이 제공되지 않습니다.

물론 전처리된 CSS 역시 style.module.scss와 같이 CSS 모듈처럼 사용이 가능합니다. 똑같이 파일 확장자에 .module만 붙여주세요.

페이지 내 CSS 주입 비활성화하기

CSS 콘텐츠의 자동 주입은 ?inline 쿼리 매개변수를 통해 비활성화 할 수 있습니다. 이 경우 처리된 CSS 문자열은 평소와 같이 모듈의 default export로 반환되나, 스타일은 페이지에 주입되지 않습니다.

import styles from './foo.css' // 페이지에 스타일이 추가됨
import otherStyles from './bar.css?inline' // 페이지에 스타일이 추가되지 않음

정적 에셋

정적 에셋을 Import 하는 경우, 이에 대한 Public URL이 반환됩니다.

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

URL 쿼리를 이용해 에셋을 가져올 때 어떻게 이를 가져올 것인지 명시할 수도 있습니다.

// URL로 에셋 가져오기
import assetAsURL from './asset.js?url'
// String 타입으로 에셋 가져오기
import assetAsString from './shader.glsl?raw'
// 웹 워커 가져오기
import Worker from './worker.js?worker'
// Base64 포맷의 문자열 형태로 웹 워커 가져오기
import InlineWorker from './worker.js?worker&inline'

좀 더 자세히 알고 싶다면, 정적 에셋 핸들링하기 섹션을 참고해주세요.

JSON

JSON 파일은 바로 Import가 가능합니다. 물론, 가져올 필드를 지정할 수도 있습니다.

// 객체 형태로 가져오기
import json from './example.json'
// 필드를 지정해 가져오기 (트리-쉐이킹 됩니다.)
import { field } from './example.json'

동적 Import

Glob Import와 마찬가지로 Vite는 변수를 사용한 동적인 Import도 지원합니다.

const module = await import(`./dir/${file}.js`)

변수 file은 깊이가 1인 파일에 대해서만 나타낼 수 있습니다. 가령 file이 foo/bar인 경우에는 Import가 실패하게 됩니다. 좀 더 다양한 기능이 필요한 경우에는 Glob Import 기능을 사용해주세요.

 

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 접미사를 붙여 가져올 수 있습니다. 모듈의 export default 로는 워커의 생성자가 들어가게 됩니다.

import MyWorker from './worker?worker'

const worker = new MyWorker()

물론, import 대신 importScripts() 함수*를 이용할 수도 있습니다. 다만 이 경우 개발 환경에서는 브라우저의 네이티브 API에만 의존하여 크롬에서만 동작한다는 것을 유의해주세요. 물론 프로덕션 빌드 시 다양한 브라우저를 지원하도록 컴파일됩니다. (* importScripts() MDN doc)

마지막으로, 기본적으로 워커의 경우 프로덕션 빌드 분리된 청크로 컴파일됩니다. 만약 분리된 청크가 아니라 Base64 포맷의 문자열로 이를 사용하고자 한다면, inline 쿼리를 이용해주세요:

import MyWorker from './worker?worker&inline'

만약 워커를 URL로 검색하고자 한다면, url 쿼리를 추가해주세요:

import MyWorker from './worker?worker&url'

모든 워커에 대한 번들링 설정은 워커 옵션을 참고해주세요.

 

 

 

필요한 부분만 발췌해서 옮겼다. 아래 링크를 통해 더 자세히 살펴 볼 수 있다.

https://vitejs-kr.github.io/guide/features.html#build-optimizations

 

Vite

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

vitejs-kr.github.io

 

728x90
반응형