Next.js でブラウザ側(クライアントサイド)に公開した NEXT_PUBLIC_ な環境変数の注意点
NEXT_PUBLIC_
プレフィックスをつけておくだけでしょ?と思ってたらうまく読み取れずにハマったのでメモです
結論
環境変数の読み取り方も大事
クライアントサイドで環境変数を読み取るときは、回りくどい方法で環境変数を取得するのはやめて process.env.NEXT_PUBLIC_xxx
直打ちで取得するのがベター
まあふつーに読めば問題ないです
ブラウザに環境変数を公開する方法
ドキュメントにもある通り、NEXT_PUBLIC_
をつけるだけでブラウザ側に公開されます
In order to expose a variable to the browser you have to prefix the variable with NEXT_PUBLIC_
何にハマったか
以下のような便利関数を経由して環境変数を取得していました
type NameToType = {
readonly ENV: 'production' | 'staging' | 'development' | 'test';
...
};
export function getEnv<Env extends keyof NameToType>(name: Env): NameToType[Env];
export function getEnv(name: keyof NameToType): NameToType[keyof NameToType] {
const val = process.env[name];
if (!val) {
throw new Error(`Cannot find environmental variable: ${name}`);
}
return val;
}
この関数を使うと環境変数の名前によって返り値の型が推論されるので便利なのですが
この関数を使って .env
ファイルで定義した NEXT_PUBLIC_
プレフィックスな環境変数をブラウザから取得しようとしてもエラーになってしまいます
原因
こちらは next.config.js の env フィールドについての説明ですが、次のように書いてあります
Next.js will replace process.env.customKey with 'my-value' at build time. Trying to destructure process.env variables won't work due to the nature of webpack DefinePlugin.
Webpack の DefinePlugin を使って単に process.env.xxx な文字列を環境変数の値に置換しているだけので、destructure してると上手く動かないよ、とのことです
NEXT_PUBLIC_
プレフィックス付き環境変数についてもおそらく同様の方法で展開されているので同じ制約がかかるという訳です
上で紹介した getEnv
関数のように process.env['NEXT_PUBLIC_xxx']
とアクセスしたり const { NEXT_PUBLIC_xxx } = process.env
と分割代入していたりするとうまく動かないわけですね
getEnv
で取得するのはやめて、直接 process.env.NEXT_PUBLIC_xxx
と取得するようにしたことで上手く動くようになりました
まとめ
クライアントサイドで環境変数を読み取るときは、回りくどい方法で環境変数を取得するのはやめて process.env.NEXT_PUBLIC_xxx
直打ちで取得するのがベター
ブラウザ側で process.env オブジェクトが作られてそこに NEXT_PUBLIC_
プレフィックスな環境変数がいい感じに生えてくるような挙動と思っていたので1時間ぐらいハマっちゃいました
Discussion