Viteを使って個人開発してる中で地味に詰まったのでメモ。
Summary
- Vite の環境変数は
vite.config.tsにおけるenvDirで指定したディレクトリパスにある.envを参照する .envの情報はimport.meta.env内に保持されるVITE_prefix がつく環境変数のみを.envファイルから取得し、それ以外は undefined となる- TS 用の型補完は
vite/client.d.tsで型定義を提供しており、自前型定義はImportMetaEnvを補う形で追加する
ref: Env Variables and Modes | Vite
Contents
① Vite の環境変数は vite.config.tsにおける envDir で指定したディレクトリパスにある .env を参照する
- ref: https://ja.vitejs.dev/config/shared-options.html#envdir
- デフォルトでは
rootとなっている - これは
vite.config.tsで指定しているrootをベースとしているため、下記のようなディレクトリ構成、設定の場合は指定が必要
- public/ - src/ └ main.ts └ index.html - .env - package.json - yarn.lock - vite.config.ts
vite.config.ts
import { defineConfig } from "vite"; export default defineConfig({ root: "src", // src 配下を root としたい envDir: "../", // src がroot のため、envDir は1つ戻す publicDir: "../public", build: { outDir: "../dist", }, server: { port: 9000, }, });
うっかりで地味に気づくのに時間かかった。。
② .env の情報は import.meta.env 内に保持される
Vite でビルドした結果において、環境変数は import.meta.env に保持される。
標準で下記のような情報を保持している。
import.meta.env.BASE_URL... アプリのベースURL。import.meta.env.DEV... 開発環境で動作しているかどうかimport.meta.env.PROD... 本番環境で動作しているかどうかimport.meta.env.MODE... アプリのモード。yarn build --mode {mode}のように文字列指定できる。yarn devはdevelopmentモード、buildはproductionモードとして動作するimport.meta.env.SSR... SSR での動作かどうか
③ VITE_ prefix がつく環境変数のみを .env ファイルから取得し、それ以外は undefined となる
Vite は標準で dotenvを内包している。
現在のモードに合わせて、下記のように読み込む条件が変わる。
- .env # 全ての場合に読み込まれる - .env.local # 全ての場合に読み込まれ、gitには無視される - .env.[mode] # 指定されたモードでのみ読み込まれる - .env.[mode].local # 指定されたモードでのみ読み込まれ、gitには無視される
少し変わった特徴として、Viteでは環境変数が誤ってクライアントサイドに漏れないように、 VITE_ prefix がつく変数のみをViteで処理されたコードに公開する。
sample
VITE_HOGE=aaa HOGE=bbb
これに対し、 クライアントサイドで取得を試みると下記のようになる。
import.meta.env.VITE_HOGE... aaaimport.meta.env.HOGE... undefined
デフォルトは VITE_ という指定だが、この prefix は enxPrefix を vite.config.ts に指定して変更可能。
Viteのコードを追ってみると、シンプルに .env で読み取った情報の中から prefix が一致するものだけを吸っているっぽい。
④ TS 用の型補完は vite/client.d.ts で型定義を提供しており、自前型定義は ImportMetaEnv を補う形で追加する
Viteの import.meta.env の型定義は vite/client.d.ts で提供されている。
しかし、自前の環境変数には自動補完が効かないので、下記のような env.d.ts を作成する。
/// <reference types="vite/client" /> interface ImportMetaEnv { readonly VITE_APP_TITLE: string; readonly VITE_HOGE: string; readonly VITE_FUGA: string; /// etc... } interface ImportMeta { readonly env: ImportMetaEnv; }