Next.jsアプリをVercelにデプロイしたところ、ダッシュボードで設定した環境変数SUPABASE_URLの値がブラウザ側のコンポーネントからアクセスするとundefinedになる。サーバーサイドのAPI Routeからは正常に取得できている。この問題の原因として正しいものはどれか。
解説
Next.jsでは、クライアントサイド(ブラウザ)で環境変数を参照するには、変数名をNEXT_PUBLIC_で始める必要があります。このプレフィックスがない環境変数はビルド時にクライアント向けのJavaScriptバンドルに含まれず、ブラウザからはundefinedになります。これはVercelの制限ではなくNext.jsの仕様であり、サーバーサイドの秘匿情報が誤ってクライアントに漏洩するのを防ぐためのセキュリティ設計です。したがって、この例ではダッシュボード上の変数名をNEXT_PUBLIC_SUPABASE_URLに変更し、再デプロイすれば解決します。プランによる制限ではなく、ブラウザキャッシュも無関係です。また、process.env自体はNext.jsのビルドプロセスで文字列置換されるため、ブラウザでも動作します(ただしNEXT_PUBLIC_付きの変数のみ)。ビルド時置換の仕組みを理解するNext.jsはビルド時にprocess.env.NEXT_PUBLIC_XXXを実際の値にインライン置換します。つまり、ランタイムに動的に参照しているのではなく、ビルド成果物に文字列として埋め込まれます。これが意味するのは、環境変数を変更したら再デプロイが必須だということです。ダッシュボードで値を変えただけでは反映されません。よくあるミスと実務での注意点APIキーをNEXT_PUBLIC_で公開してしまう: NEXT_PUBLIC_付きの値はブラウザのDevToolsから誰でも見えます。Supabaseのanon keyのように公開前提のキーはよいですが、service_role keyのような秘匿キーには絶対にNEXT_PUBLIC_を付けないでください環境の指定漏れ: Vercelダッシュボードでは環境変数をProduction・Preview・Developmentの各環境に個別に割り当てられます。Productionにだけ設定してPreviewに設定し忘れると、プルリクエストのプレビューデプロイで値が取れないという事故が起きます変数追加後にデプロイし忘れる: 前述のとおりビルド時置換のため、ダッシュボードで変数を追加・変更した後は必ず再デプロイしてください