최근에 Vue.js 3 + Typescript 로 개인프로젝트를 진행을 하였다.
해당 프로젝트는 Vite 라는 도구를 활용하여 구성이 되었으며(Rollup.js 기반)
여기서 좀 헤매였던점은 .env 에 있는 속성값들을 사용하고 싶었는데 생각처럼 잘 되지 않았던 이슈였다.
import.meta
ES2021(ES12) 에 새로 추가된 기능이다.
모듈 컨텍스트(module context) 특정 meta 데이터를 공개한다고 설명이 되어있다.
<script type="module" src="my-module.js"></script>
console.log(import.meta); // { url: "file:///home/user/my-module.js" }
위 예제에서 확인이 가능한거처럼, 모듈에 대한 정보를 제공해주는 객체다.
Vite ?
Vue CLI 와 같은 기본 프로젝트 생성 및 개발 환경을 제공해주는 도구다.
Vue CLI 와 다른점은 native ES module 기반으로 개발환경을 제공해주고 있기때문에 상대적으로 빠르다.(개발중에 번들링을 하는게 아니다.)
<script type='module'>
형식으로 해석을 한다. 실제 공식 홈페이지에 가서 문서를 살펴보면, CJS(CommonJS) 와 UMD(Universal Module Definition) 모듈을 ESM 으로 변환시킨다고 되어있다.(esbuild 로 수행)
HMR 같은 경우도 native ES module 로 제공하기떄문에, 속도가 빠릅니다.(개발중에도 필요한 모듈만 로드함)
.env, env.local 등
을 정의해서 사용하면 된다. 그리고 실제 클라이언트에 .env 속성을 노출시킬려면 VITE_
접두사를 사용해야한다.import.meta.env
를 통해서 속성을 노출시킨다.declare const __MODE__: string
declare const __DEFINES__: Record<string, any>
const context = (() => {
if (typeof globalThis !== 'undefined') {
return globalThis
} else if (typeof self !== 'undefined') {
return self
} else if (typeof window !== 'undefined') {
return window
} else {
return Function('return this')()
}
})()
// assign defines
const defines = __DEFINES__
Object.keys(defines).forEach((key) => {
const segments = key.split('.')
let target = context
for (let i = 0; i < segments.length; i++) {
const segment = segments[i]
if (i === segments.length - 1) {
target[segment] = defines[key]
} else {
target = target[segment] || (target[segment] = {})
}
}
})
어찌되었든 이제 알겠다.. 그런데 Typescript 에서 사용을 하려면 유형정의를 제공해줘야한다.
env.d.ts 를 작성을 하면되는데 아래와 같이 작성을 해주면 된다.
interface ImportMeta {
env: {
VITE_BASE_URL?: string,
VITE_API_KEY?: string,
}
}
VITE_BASE_URL=https://api/v1/
VITE_API_KEY=블라블라블라
Typescript 를 따로 공부를 해본적은 없어서, *.d.ts 가 무엇을 의미하는가 좀 찾아보았다.
선언(declare) 을 의미하는 파일이라고 되어있는데, 단순히 타입을 선언하기도 하고 모듈을 선언하기도 한다.
결론적으로는 env.d.ts 는 .env 에 대한 유형정보를 제공한다고 생각하면 된다.