← ./articles-ja

Viteのenv変数が更新されない時はdev server再起動とcacheを確認する

Viteは import.meta.env でenv変数を便利に扱えます。しかしその便利さには罠があります。.env を編集して保存すれば、hot module replacementで実行中のappも更新されると思いがちです。

通常そうはなりません。Viteはdev server起動時に .env filesを読みます。source filesはhot reloadされますが、env filesはstartup inputです。

症状: import.meta.envがundefinedまたは古い

よくある失敗です。

console.log(import.meta.env.VITE_API_BASE_URL);

値が undefined、または .env を編集しても古いURLのままです。

まず名前を確認します。

VITE_API_BASE_URL=https://api.example.test

client codeへ公開されるのは、defaultでは VITE_ prefixを持つ変数だけです。API_BASE_URL はprocess environmentに存在しても import.meta.env には出ません。

.env変更後は再起動する

.env を変えたらdev serverを止めて再起動します。

Ctrl+C
npm run dev

application codeを変える前にこれを試します。Vite docsでも .env filesはstartup時にloadされるため、編集後のstale valueは自動的にcode bugとは限りません。

productionとdevelopmentのenv fileを分ける

production buildに入れてはいけない値はmode-specific fileに分けます。

.env
.env.development
.env.production

例です。

# .env.development
VITE_DEBUG_TRIAL_STATE=active 5
VITE_FORCE_ONBOARDING=true
# .env.production
VITE_PUBLIC_SITE_URL=https://example.com

build modeがどのfileを読むかを決めるため、productionからdev-only値を消す防御codeを減らせます。

TypeScriptにcustom envを宣言する

TypeScriptに変数名を認識させます。

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

interface ImportMetaEnv {
  readonly VITE_API_BASE_URL: string;
  readonly VITE_DEBUG_TRIAL_STATE?: string;
  readonly VITE_FORCE_ONBOARDING?: string;
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}

VITE_API_BASEURL のようなtypoを早く見つけられます。

import.meta.env.DEVだけに頼らない

import.meta.env.DEV は便利ですが、危険なdebug pathをproductionから守る唯一の条件にしないほうが安全です。

明示的なdebug variableを使います。

const debugTrialState = import.meta.env.VITE_DEBUG_TRIAL_STATE ?? "";

if (debugTrialState) {
  // dev-only simulation path
}

production buildではstripまたはrejectします。

export default defineConfig(({ mode }) => ({
  define:
    mode === "production"
      ? { "import.meta.env.VITE_DEBUG_TRIAL_STATE": JSON.stringify("") }
      : {},
}));

licensing、payment、auth、customer dataに関わるdebug flagなら、productionで設定されていたらbuild failにします。

どうしても変ならVite cacheを消す

まれにVite cacheでdev sessionが違うmodeのように振る舞います。stale envより強い症状、つまりdev-only codeがdev commandでも動かない場合です。

cacheを消します。

rm -rf node_modules/.vite .vite
npm run dev

PowerShellでは:

Remove-Item -Recurse node_modules\.vite, .vite -ErrorAction SilentlyContinue
npm run dev

prefix、server restart、mode-specific filesを見た後に試します。

build後のHTML placeholderも確認する

ViteはHTML内の %VITE_*% placeholderを置換できます。

<a href="%VITE_CHECKOUT_URL%">Buy now</a>

build outputを確認します。

npm run build
grep -R "%VITE_" dist

dist にplaceholderが残っているなら、build時に変数がありません。

チェック順

  1. 変数名が VITE_ で始まるか
  2. .env 編集後にdev serverを再起動したか
  3. .env.development / .env.production に分けるべき値か
  4. vite-env.d.ts に宣言したか
  5. build後の dist に未解決placeholderがないか
  6. それでもだめなら .vite cacheを消す

参考