本記事の概要
Viteで.envが読まれないの、どうしよう~
解決
ソースコード(修正後)
import { defineConfig, loadEnv } from 'vite'
import react from '@vitejs/plugin-react-swc'
import { resolve } from "node:path";
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, __dirname, '')
return {
// vite の設定
base: "./",
root: "src",
plugins: [
react()
],
build: {
// distフォルダに出力
outDir: resolve(__dirname, "dist"),
// 存在しないときはフォルダを作成する
emptyOutDir: true,
copyPublicDir: true,
rollupOptions: {
// entry pointがあるindex.htmlのパス
input: {
"": resolve(__dirname, "src/index.html"),
},
// bundle.jsを差し替えする
output: {
entryFileNames: "assets/bundle.js",
},
},
},
define: {
'process.env': env,
},
}
})
const env = process.env;
console.log(env);
ENV_HAS_READ_DEVELOP=true
VITE_ENV_HAS_READ=true
下記「ソースコード(修正前)」の該当ファイルを上記のものに差し替えた状態でnpm run dev
を行った結果;
→ 環境変数ENV_HAS_READ_DEVELOP
ならびにVITE_ENV_HAS_READ
が読み込まれていることが確認できた。
症状
ソースコード(修正前)
{
"name": "myapp",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite"
},
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@types/react": "^18.3.10",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react-swc": "^3.5.0",
"eslint": "^9.11.1",
"typescript": "^5.5.3",
"typescript-eslint": "^8.7.0",
"vite": "^5.4.8"
}
}
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import { resolve } from "node:path";
export default defineConfig({
base: "./",
root: "src",
plugins: [
react()
],
build: {
outDir: resolve(__dirname, "dist"),
emptyOutDir: true,
copyPublicDir: true,
rollupOptions: {
input: {
"": resolve(__dirname, "src/index.html"),
},
output: {
entryFileNames: "assets/bundle.js",
},
},
},
}
)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<title></title>
<script type="module" src="/main.tsx"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.tsx'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
)
console.log(import.meta.env);
const env = process.env;
console.log(env);
function App() {
return (<></>);
}
export default App
ENV_HAS_READ=true
VITE_ENV_HAS_READ=true
ENV_HAS_READ_DEVELOP=true
VITE_ENV_HAS_READ=true
ENV_HAS_READ_PRODUCTION=true
VITE_ENV_HAS_READ=true
結果
npm run dev
でブラウザで開き、コンソールを見ると
{BASE_URL: '/', DEV: true, MODE: 'development', PROD: false, SSR: false}BASE_URL: "/"DEV: trueMODE: "development"PROD: falseSSR: false[[Prototype]]: Object
App.tsx:4 Uncaught ReferenceError: process is not defined
at App.tsx:4:13
Viteのimport.meta.env
が存在し、MODE=developmentになっているが、環境変数が読み込まれていない。
Viteでは仕様上、VITE_
のフレフィックスをもつ環境変数をimport.meta.env.VITE_****
で利用できるハズだが
import.meta.env
以下に存在していない。
失敗
Viteにおいて環境変数の対応は本来Viteが行ってくれているが、
これを無視してdotenvを無理やり使うことを試みる。
ソースコード
npm install dotenv
からの
import * as dotenv from 'dotenv';
if (import.meta.env.PROD) {
dotenv.config({ path: '.env' });
dotenv.config({ path: '.env.production' });
}
if (import.meta.env.DEV) {
dotenv.config({ path: '.env' });
dotenv.config({ path: '.env.develop' });
}
if (process.env.ENV === 'local') {
dotenv.config({ path: '.env' });
dotenv.config({ path: '.env.local' });
}
const env = process.env;
export default env;
import env from "./env";
console.log(import.meta.env);
console.log(env);
function App() {
return (<></>);
}
export default App
結果
そこからの試み
よく分からないが、process
はNode.jsで動くものであって、ブラウザ上で動くものではないと勝手に考察した。
まずはprocess
を強引に作ってみる
こちらの記事を参考に;
export default defineConfig({
....
define: {
'process.env': {}
}
}
)
vite.config.ts
のdefineオプションに入れたものはグローバル変数になる(?)という知見が得られた。
空のオブジェクトを入れたのでエラーが出るのは当然。
多分、process
に本来格納されるべきオブジェクトをそのまま入れないとダメなのだろう。そこまでするのは面倒なので、Viteの環境変数ヘルパーから得られた値をここへ入れてみる。
→ 「解決」セクションへ続く
(※結局npm install dotenv
は不要でした)
もう一つの解決法
vite-plugin-env-compatible
を使用
→ 参考:Uncaught ReferenceError: process is not definedが表示される
ソースコード
npm install vite-plugin-env-compatible
からの
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import env from "vite-plugin-env-compatible";
import { resolve } from "node:path";
export default defineConfig({
base: "./",
root: "src",
plugins: [
react(),
env({ prefix: "VITE", mountedPath: "process.env" })
],
build: {
outDir: resolve(__dirname, "dist"),
emptyOutDir: true,
copyPublicDir: true,
rollupOptions: {
input: {
"": resolve(__dirname, "src/index.html"),
},
output: {
entryFileNames: "assets/bundle.js",
},
},
},
}
)
結果
VITE_ENV_HAS_READ
が読み込まれたので、.env
ファイルが評価されている。
が、vite-plugin-env-compatible
でmode
に応じて読み込む.env
ファイルを変える方法がいまいち分からなかったため、今回は採用しなかった。