
目次
自社サービスやWebアプリをスクラッチ開発していると、ほぼ必ず一度は踏む落とし穴があります。ローカルでは動くのに、本番環境だけ値が入らないという現象です。
先日も、環境変数を正しく設定したはずなのに本番でundefinedになり、原因の切り分けに半日かかった案件がありました。設定画面を何度見返しても値は入っている。綴りも合っている。それでも動かない——結論から言うと、問題は設定値ではなくコード側の書き方にありました。
この記事では、Next.jsのNEXT_PUBLIC_付き環境変数がなぜ本番でundefinedになるのか、そして同じ半日を使わないための確認順序を整理します。
この記事の結論
NEXT_PUBLIC_付きの変数はビルド時に値へ置き換えられる- 動的アクセスは置換対象にならず、必ずundefinedになる
- 本番だけ動かないときは、設定値より書き方とビルドを疑う
NEXT_PUBLIC_環境変数が本番でundefinedになる原因
まず仕組みから押さえます。NEXT_PUBLIC_という接頭辞がついた環境変数は、ブラウザ側のコードから読めるようにするためのものです。ただし、ブラウザは実行時にサーバーの環境変数を取りにいくわけではありません。ビルドの時点で、コード内の記述がそのまま値の文字列に置き換えられます。
つまり、ブラウザに届いた時点では環境変数という概念すら残っていません。ここから2つの重要な性質が出てきます。
1つは、設定を変えたら再ビルドしないと反映されないこと。管理画面で値を直しても、ビルド済みのファイルには古い値が焼き付いたままです。
もう1つが、今回の犯人でした。
動的アクセスは置換されない:NGな書き方とOKな書き方
置換は、コード上の文字列を機械的に探して行われます。そのため、変数を経由した参照は「置き換えるべき場所」として認識されません。
// NG:変数経由の参照。置換されずundefinedになる
const key = "NEXT_PUBLIC_API_URL";
const url = process.env[key];
// OK:キー名をそのまま書く。ビルド時に値へ置換される
const url = process.env.NEXT_PUBLIC_API_URL;
| 書き方 | ビルド時の置換 | 本番での結果 |
|---|---|---|
process.env.NEXT_PUBLIC_API_URL | される | 値が入る |
process.env["NEXT_PUBLIC_API_URL"] | 環境により差がある | 要検証 |
process.env[変数] | されない | undefined |
厄介なのは、ローカルの開発サーバーでは動いてしまうことがある点です。開発時はサーバー側で実行される経路があり、実行時に環境変数を読めてしまうため、問題が表面化しません。本番ビルドで初めて露見する——だからこそ切り分けが長引きます。
なお、この置換の挙動はフレームワークのバージョンによって変わりうるため、最新の条件は必ず公式ドキュメントで確認してください。
切り分けを迷わせた2つの落とし穴
原因は1行の書き方でしたが、そこに辿り着くまでに半日かかりました。回り道をさせた要因が2つあります。
落とし穴1:管理画面でキー名が省略表示される
ホスティングサービスの管理画面では、環境変数のキー名が長いと途中で省略表示されることがあります。画面上は正しく見えていても、末尾の一文字が違っていないかを目視で確認できない。「設定は合っているはず」という前提が揺らぎ、確認に無駄な時間を使いました。省略表示に頼らず、ホバーや編集画面でフルのキー名を確認するのが確実です。
落とし穴2:環境ごとに別管理で、片方だけ反映漏れ
多くのホスティングサービスでは、本番・プレビュー・開発といった環境ごとに環境変数を別々に管理します。プレビューには設定したが本番には入れていない、あるいはその逆、という反映漏れが起こります。今回も「プレビューでは動くのに本番で動かない」という状態が、原因の判断を鈍らせました。
この2つは技術的には単純な話ですが、現象が同じ(本番だけundefined)なので、原因の見分けがつきません。だからこそ、確認の順序を決めておく価値があります。
対策:確認する順序を先に決めておく
本番だけ値が入らないときは、次の順で見ます。
- 参照の書き方を見る:
process.env.のあとにキー名をべた書きしているか。変数経由になっていないか。ここが最も見落としやすく、かつ最も確実に原因を潰せます。 - ビルドのタイミングを見る:環境変数を設定・変更したあとに再ビルドしたか。設定を直しただけでは反映されません。
- 環境ごとの設定とキー名を見る:本番用の環境に値が入っているか。省略表示に惑わされず、フルのキー名で照合します。
多くの人は3から手をつけます。設定画面が目に見えるからです。しかし実際の原因は1にあることが多く、順序を逆にするだけで切り分け時間が大きく変わります。
持ち帰る判断軸:本番だけ動かないときは「設定値」を疑わない
この件から取り出せる原則は、シンプルな一文にまとまります。
本番だけ値が入らないときは、設定値ではなく参照の書き方とビルドのタイミングを疑う。
「設定したのに動かない」とき、人はまず設定値そのものを疑います。しかし今回のように、設定値は最初から正しく、値が届く経路のほうが壊れているケースは珍しくありません。ローカルと本番で挙動が違うなら、両者で異なるのは環境変数の中身ではなく、ビルドの有無や実行される場所です。そこを先に見る習慣をつけると、調査の時間は目に見えて短くなります。
これは環境変数に限った話ではありません。キャッシュ、ビルド成果物、CDN——中小企業のWeb開発でも、「本番だけ違う」現象の多くは、値ではなくタイミングと経路の問題です。
よくある質問
Q. NEXT_PUBLIC_をつけたのに本番でundefinedになるのはなぜですか?
NEXT_PUBLIC_付きの変数はビルド時に値へ置き換えられるため、設定後に再ビルドしていないと古い値のままになります。参照の書き方が動的な場合も置換されず、undefinedになります。
Q. process.env[変数名]のような動的な書き方はなぜ動かないのですか? 置換はコード上の文字列を機械的に探して行われるため、変数経由の参照は対象として認識されません。結果、実行時に何も入らずundefinedになります。キー名は直接べた書きで参照してください。
Q. ローカルでは動くのに本番だけ動かない場合、どこを確認すればいいですか? 設定値そのものより先に、参照の書き方とビルドのタイミングを疑います。次にホスティング側の環境ごとの設定、最後にキー名の綴りという順で確認すると、切り分けの時間を短くできます。
まとめ
NEXT_PUBLIC_付きの環境変数は、ビルド時に値へ静的に置換される仕組み- 変数経由の動的アクセスは置換対象にならず、本番で必ずundefinedになる
- 管理画面のキー名省略表示と、環境ごとの別管理が切り分けを迷わせる
- 確認は参照の書き方→ビルドのタイミング→環境ごとの設定の順で行う
RENOYでは、Next.jsなどを用いたスクラッチ開発と、その後の運用・保守までを一貫して支援しています。「開発は外注したが、こうした不具合の原因が社内で分からない」という状態こそ、中小企業にとって一番コストのかかるリスクです。技術的な相談はもちろん、開発体制の見直しからでも承っています。まずはお気軽に無料個別相談(オンライン・60分)をご利用ください。サービス内容をまとめた資料は資料請求からご覧いただけます。
