Node.js で dotenv の値が読み込めない
.env が読まれない原因はほぼ「呼ぶ順序が遅い」「ファイルの場所が違う」「Node 20.6+ の --env-file と二重読み」のいずれか。
エントリで最初に dotenv.config() を呼び、import 順を意識すれば解決する。
#nodejs#dotenv#env#process.env#--env-file
公開:
要約
dotenv が読まれないと感じる場面のほとんどは「読み込みのタイミング」が遅い。
他モジュールの import 評価より 先に dotenv.config() を実行する必要があり、ESM では特に順序が問題になる。
Node.js 20.6 以降は標準で --env-file を持っているため、新規プロジェクトでは dotenv 自体不要なケースも増えている。
よくある原因
- 呼び順が遅い:
import config from "./config"の中でprocess.env.FOOを読むのに、dotenv.config()がその後ろにある - カレントディレクトリのズレ:
npm startを別ディレクトリから走らせ、.envがプロジェクトルートに無いと dotenv は見つけられない - ESM の評価順: ESM の
importはトップレベルで実行されるが、同じファイル内の通常文より前に動く。dotenv.config()をimportの後ろに書いても、他importには間に合わない - --env-file との二重読み:
node --env-file=.env app.jsとdotenv.config()の両方を併用すると、片方が空文字で上書きすることがある
解決策
1. エントリ最上部で読み込む
CommonJS の場合。
// index.js
require("dotenv").config();
const app = require("./app"); // この時点で process.env が揃っているESM の場合。
// main.mjs
import "dotenv/config"; // ← 最初の import
import { app } from "./app.mjs";dotenv/config を import するだけで config() が自動実行される。
2. パスを絶対指定する
import { config } from "dotenv";
import path from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
config({ path: path.resolve(__dirname, "../.env") });npm start の起動位置に依存しなくなる。
3. --import で preload する(ESM)
node --import "dotenv/config" app.mjs--import フラグで指定したモジュールは、アプリの最初の import より前に評価される。package.json の scripts に書いておく。
{
"scripts": {
"start": "node --import dotenv/config app.mjs"
}
}4. Node 20.6+ なら --env-file 単独に
node --env-file=.env app.jsdotenv ライブラリを外し、Node 標準機能だけで完結させる。
複数の env ファイルを読みたい場合は --env-file を複数回指定できる(後勝ち)。