Menu

Node.js process.envの使い方:環境変数を読む

process.envは、Node.jsのプログラムを起動したときの環境変数を持つオブジェクトです。値はすべて文字列かundefinedなので、数値や真偽値は自分で変換し、変数ごとにデフォルト値を用意します。

このページのコードはエディタで実行できます。編集してすぐに結果を確認できます。

process.env は、シェルがNode.jsのプログラムに渡した環境変数を1つずつプロパティとして持つオブジェクトです。process.env.PORT、process.env.DATABASE_URL のように読みます。設定されていない変数は undefined になり、設定されている変数は必ず文字列です。起動時に1回読み、デフォルト値を与え、必要な型に変換しましょう。

shop on port 8080 in eu-west と表示されました(REGION は設定されていないのでデフォルト値が使われました)。続いて string number と表示されています。変数は Number() で変換するまでテキストのままです。最初の2つの代入を消して実行し直すと、すべてデフォルト値になります。

シェルで環境変数を設定する

変数は、Node.jsを起動した場所から来ます。ターミナルでは次のようにします。

// macOS and Linux: for one command
PORT=8080 NODE_ENV=production node app.js

// macOS and Linux: for the rest of the terminal session
export PORT=8080

// Windows PowerShell
$env:PORT = "8080"; node app.js

// Windows cmd.exe
set PORT=8080
node app.js

ホスティング環境(Heroku、Render、Vercel、Docker、Kubernetes)には、同じことをする設定画面や設定ファイルがあります。コード側の読み方は変わりません。

すべては文字列

process.env のバグの大半はここから生まれます。'false' と '0' は空でない文字列なので、truthyです。

素朴なチェックでは、false に設定した変数でも debug is ON と表示されました。期待する文字列そのものと比較しましょう。数値の場合、Number(process.env.X) は値がないと NaN になるので、最初の例で ?? を使ったように、変換する前にデフォルト値を適用します。

NODE_ENV

NODE_ENV はNode.jsの機能ではなく慣習です。Node.jsがこれを設定することはありません。読むのはライブラリです。たとえばExpressは、これが production だとエラーページにスタックトレースを出さなくなり、多くのツールは開発時だけのチェックを省きます。

mode: production と verbose logs: false が表示されました。'production' を 'development' に変えると、2行目が逆になります。ライブラリはこの単語そのものを確認するので、production、development、test のどれかを使いましょう。

.envファイル:--env-fileとdotenv

node の前に毎回すべての変数を書くのは面倒です。.env ファイルなら、プロジェクトのフォルダに1行に1つずつ置いておけます。

// .env
PORT=8080
DATABASE_URL=postgres://localhost/shop
API_KEY=dev-key-123

Node.js 20.6以降は、パッケージなしでフラグ1つで読み込めます。

node --env-file=.env app.js

古いバージョンの場合や、こちらのほうが好みなら、dotenv パッケージをインストールし(npm install dotenv)、エントリーファイルの一番上、process.env を読むコードより前で読み込みます。

require('dotenv').config(); // copies .env into process.env

console.log(process.env.PORT); // 8080

どちらもシェルですでに設定されている変数は上書きしないので、本番の設定がファイルより優先されます。

足りない変数は早めに失敗させる

データベースのURLがないなら、1時間後の最初のリクエストでクラッシュするのではなく、起動時にわかりやすいメッセージを出して止まるべきです。

Missing environment variables: API_KEY と表示されました。先頭に process.env.API_KEY = 'test'; を足すと Config OK と表示されます。実際のプログラムではメッセージの後に process.exit(1) を書きましょう。デプロイスクリプトやコンテナ基盤は、0以外の終了コードを見て起動に失敗したと判断するからです。

秘密情報は絶対にコミットしない

.env は作ったその日に .gitignore に入れましょう。代わりに、変数名とダミーの値を書いた .env.example をコミットしておけば、ほかの人も何を設定すればいいかわかります。一度でもリポジトリにプッシュしたキーは、後でコミットを消したとしても漏れたものとして扱い、作り直してください。

よくある質問

process.env.MY_VARがundefinedになるのはなぜですか?

Node.jsを起動したシェルで変数が設定されていないか、別のターミナルで設定されています。.env ファイルも自動では読まれません。値を読む前に、--env-file=.env を付けてNode.jsを起動するか、dotenv で読み込んでください。

実行中にprocess.envを変更できますか?

できます。process.env.X = 'value' と代入すると、今のプロセスと、その後に起動する子プロセスでは値が変わりますが、Node.jsを起動したシェルには影響しません。代入した値はNode.jsが文字列に変換します。

環境変数の名前は大文字と小文字を区別しますか?

LinuxとmacOSでは区別します。PORT と port は別の変数です。Windowsでは区別しません。アンダースコア入りの大文字の名前に統一しておけば、この問題は起きません。

ブラウザからprocess.envを読めますか?

読めません。ブラウザには環境変数がありません。ViteやNext.jsのようなビルドツールは、選んだ変数をビルド時にフロントエンドのコードへコピーします。つまり、その値は公開されるということです。

Coddyのプログラミング言語のイラスト

Coddyでコードを学ぼう

始める