Next.js アプリ内での環境変数の振る舞い
process.env の振る舞い
Node.js の process.env
による環境変数の参照が有効なのは、基本的には次のようなサーバーサイドで実行されるコード内のみです。
- ビルド時あるいはアクセス時に呼び出される
getStaticPaths
やgetStaticProps
- 必ずアクセス時に呼び出される
getServerSideProps
- 必ずアクセス時に呼び出される API ルートのハンドラ関数 (
handler
)
NEXT_PUBLIC プレフィックス
ただし、例外として、NEXT_PUBLIC_
で始まる環境変数を process.env.NEXT_PUBLIC_XXX
のように参照すると、next build
によるビルド時に変数値がインライン展開されるので、クライアントサイドで実行されるコード(コンポーネントの実装内)から参照できます。
上記のようにすると、process.env.NEXT_PUBLIC_ANALYTICS_ID
の部分には、ビルド時の環境変数 NEXT_PUBLIC_ANALYTICS_ID
の値がそこに埋め込まれ、process.env.API_SECRET_KEY
の方は必ず undefined
になります(何も表示されない)。
サーバーサイドでしか参照しない環境変数(シークレットキーなど)には、NEXT_PUBLIC_
プレフィックスを付けないように注意してください。
.env (.env.local) ファイル
Next.js サーバーは、デフォルトでプロジェクトルートに配置した .env
や .env.local
といった名前のファイルを読み込んで、process.env.XXX
で参照可能な状態にしてくれます。
ローカル開発中に、一時的にテスト用のリソースサーバーに繋ぎたいときなどに便利です。
これらの設定ファイルの中では、次のように $VAR
という形の変数展開を行えるようになっています。
.local
サフィックスが付いている方のファイルは、「Git などにコミットしないファイルですよ」という Next.js での取り決めですね。
Next.js は他にも実行環境に応じて色々な名前の環境設定ファイルを読み込むようになっています。
下記は、どのファイルがどの環境で読み込まれるかの一覧です。
ファイル | 本番環境 (next start) | 開発環境 (next dev) | テスト環境 (jest など) | Git コミット するか? |
---|---|---|---|---|
.env | ✔(4) | ✔(4) | ✔(4) | ✔する |
.env.local | ✔(2) | ✔(2) | ✔(2) | しない |
.env.production | ✔(3) | ✔する | ||
.env.production.local | ✔(1) | しない | ||
.env.development | ✔(3) | ✔する | ||
.env.development.local | ✔(1) | しない | ||
.env.test | ✔(3) | ✔する | ||
.env.test.local | ✔(1) | しない |
括弧の中の数値は、優先度を示しています(1が最大)。
複数のファイルに同じ環境変数が定義されている場合は、.local
が付いたものが優先的に使われます。
例えば、本番環境 (next start
) では、.env.production.local
> .env.local
> .env.production
> .env
という優先度になります。
末尾に .local
が付いたファイルには秘密鍵などの情報を記述することを想定しているので、間違えて Git にコミットしないように .gitignore
ファイルに登録しておきましょう。
config.ts に環境変数の値を反映させる
アプリ全体のコンフィグ用に config.ts
のようなファイルを作成しているケースは多いと思います。
この中で環境変数を参照するようにしておくと、環境 (production or development) に応じてリソースを使い分けるといったことが簡単にできます。
これは、Next.js が前述のように複数のファイルを読み分けてくれるおかげです。
ちなみに、??
という演算子は Nullish coalescing という仕組みで、左側が undefined
だったときに右側の値が使われるようになります。
つまり、上記のように記述しておくと、環境変数が設定されていればその値を使い、設定されていなければ後ろに書いたデフォルト値を使う、という振る舞いになります。
例えば、本番環境で接続先の情報を変えたいときは、次のような環境変数ファイルを作成するだけで済みます。
next start
で Next.js サーバーを起動したときや、Vercel でホスティングするときはこの設定が使われるようになります。
NODE_ENV 環境変数で開発環境と本番環境の動作を切り替える
Next.js サーバー実行時の NODE_ENV 環境変数の値は、サーバーの起動方法によって次のように設定されるようになっています。
Next.js サーバーの起動方法 | process.env.NODE_ENV の値 |
---|---|
next dev | development |
next start | production |
これを利用すると、現在の実行環境に応じて振る舞いを変更できます。
次の例では、開発環境 (next dev
) ではローカルのリソースファイルを使い、本番環境 (next start
) ではインターネット上のリソースファイルを使うようにしています。
ほとんどのユースケースは上記のような切り替えでカバーできるのですが、時々 next build
によるビルド後のサイト確認 (next start
) でも、ローカルリソースを参照したいことがあります(ファイル転送による従量課金が気になる場合など)。
このようなケースで、next start
コマンド実行時に強引に NODE_ENV
環境変数の値を development
に変えようとしても、内部で production
に上書きされてしまってうまくいきません。
こういったケースでは、next.config.js の env コンフィグ 機能を使って、ビルド時に独自の環境変数を設定してやるとうまくいきます。
next.config.js
ファイルはビルド時に処理されるので、上記のように記述しておくと、process.env.isProd
の値が、next build
実行時の NODE_ENV
変数の値によって確定します(正確には、コード内部の process.env.isProd
という部分が具体的な値に置換されます)。
プログラム内で process.env.NODE_ENV
を参照していた部分は、次のように process.env.isProd
を参照するように書き換えます。
あとは、ビルド方法や実行方法により、process.env.NODE_ENV
や process.env.isProd
の値を次のように変化させることができます(コンポーネント内のコードで参照したときの値を示していることに注意してください)。
ビルド/実行方法 | NODE_ENV の値 | isProd の値 |
---|---|---|
$ next build $ next start | 'production' | true |
$ NODE_ENV=development next build $ next start | 'production' | false |
$ next dev | 'development' | false |
実際には、NODE_ENV
環境変数を isProd
の値の制御のために使うのは混乱を招くので避けた方がいいかもしれません。
上記の結果を見るとわかるように、ビルド時に NODE_ENV=development
と指定しても、ランタイムでは NODE_ENV
の値は production
になってしまいます。
リソースの参照先を柔軟に切り替えたいときは、次のように独自の環境変数 (IS_LOCAL
) を用意するようにした方がよいでしょう。
上記の next.config.js
の例では、環境によってリソースファイルのプレフィックス情報 (process.env.imageUrlPrefix
) を切り替えているので、getImageUrl
関数は次のように簡潔に記述できます。