本文へ移動
verified onnext@16.3.5react@19
最終検証日 2026-09-26
Next.js道場

環境変数はいつ読まれるのか。ビルド時と実行時

Next.js の環境変数は、ページがいつ描かれるかで、ビルド時に読まれるか実行時に読まれるかが決まります。

読まれるのは「描いたとき」

process.env を読む行は、そのページを描いたときに動きます。だから、いつ描かれるページなのかで、読まれる値が変わります。

どこで読むかと、読まれるとき
どこで読むか読まれるとき
事前に描くページ(一覧で ○)の Server Componentビルド時
開かれたときに描くページ(一覧で ƒ)の Server Component開かれたとき
NEXT_PUBLIC_ の付いた変数ビルド時(JavaScript に埋め込まれる)

Cookie もクエリ文字列も使っていないページは、ビルド時に描かれます(キャッシュの解説)。そのページの中の process.env も、ビルド時に読まれて結果が HTML に焼き付きます。

実行時に値を変えても変わらない

同じものをビルドして、実行するときに別の値を渡しました。

.env(ビルド時)   API_BASE=build-time-value   NEXT_PUBLIC_LABEL=build-label
実行時に渡した値   API_BASE=runtime-value      NEXT_PUBLIC_LABEL=runtime-label
実行時に別の値を渡したとき(実機で確かめた)
表示された値
事前に描くページbuild-time-value
開かれたときに描くページruntime-value
NEXT_PUBLIC_LABELbuild-label

実行時の値を読んだのは、開かれたときに描くページだけでした。ほかの2つは、ビルド時の値のまま動かしようがありません。

なお、開かれたときに描くページでは、実行時に渡した値が .env の値より優先されました。公式ドキュメントの読み込み順でも、process.env がいちばん先です。

Docker で undefined になる

いちばん踏みやすいのがこの形です。

  • ビルドのとき(docker build)には値を渡さない
  • 実行するとき(docker run -e や compose の environment)にだけ渡す
ビルド時には渡さず、実行時にだけ渡したとき(実機で確かめた)
表示された値
事前に描くページundefined
開かれたときに描くページ実行時の値
NEXT_PUBLIC_ の付いた変数undefined

Docker で置くときの全体の手順(standalone で写すもの、HOSTNAME)は自分のサーバーに置くにまとめています。

直し方

値の使い道で分けます。

ブラウザで使う値(NEXT_PUBLIC_)

ビルドのときに渡します。ビルド時に JavaScript へ埋め込まれるので、実行時に渡しても届きません。

公式ドキュメントも、1つのイメージを複数の環境で使い回すと、NEXT_PUBLIC_ の値はビルド時の値で固まると書いています。環境ごとに値が違うなら、環境ごとにビルドします。

サーバーだけで使う値

そのページを開かれたときに描く形にします。connection() を先頭で待つと、そのページはビルド時に描かれなくなります。

import { connection } from 'next/server'
 
export default async function Page() {
  await connection()
  return <p>{`api=${process.env.API_BASE}`}</p>
}

実機で、この形なら一覧が ƒ になり、実行時に渡した値が出ることを確かめました。公式ドキュメントも、実行時の値を読む方法としてこの形を示しています。

NEXT_PUBLIC_ を付けずに Client Component で読むと

NEXT_PUBLIC_ の無い変数は、ブラウザ向けの JavaScript には入りません。ただし Client Component も初回の表示のためにサーバーで一度描かれるので、そのときには値が読めてしまいます。

実機では、事前に描いた HTML に値がそのまま入り、ブラウザ側では undefined になって表示が食い違いました(hydration のエラー。Hydration failed の直し方)。

秘密の値を Client Component で読まないでください。読んでいいのは、ブラウザに見えて困らない値だけで、それには NEXT_PUBLIC_ を付けます(server-only の解説)。

確かめ方

  1. pnpm build の一覧で、そのページが ○ か ƒ かを見る。○ ならビルド時に読まれている
  2. 本番と同じ手順でビルドしたもので、値が入っているかを見る。開発サーバーでは確かめられない
  3. NEXT_PUBLIC_ の値を変えたら、ビルドし直す

出典

このページの内容は上記の一次情報を基準に書いています。個人ブログや二次情報を根拠にしていません。

理解できたか試す

では、このコードはどうなりますか。

Docker でビルドして動かしています。API_BASE はビルドのときには渡さず、実行するときにだけ docker run -e で渡しました。このページを開くと、何が表示されますか。

この問題を解くこのテーマの問題 3 問