Cloud Run, Amplify, Netlify, Vercel上のNext.js環境変数事情
前の記事で環境を複数にしたのでログをNewRelicに集めようとしたら環境変数が素直に渡らないことがあったので実験しました。
## 検証したいこと
以下の2点です。
- .envファイル、next.config.js、Vercel等の設定画面の設定値はどれが勝つのか?
- middleware、サーバー、クライアントでどの環境変数が使えるのか?
## 検証方法
以下のラインナップで環境変数を設定します。説明のためVercelを例にします。
- Xenv .envファイルでの設定値
- Xconf next.config.jsでの設定値
- Xhost Vercelの設定画面での設定値 (サービス名に合わせます)
環境変数 ※1 | 観点 | |||
---|---|---|---|---|
EVTEST_ENV | E | どこで使えるか | ||
EVTEST_CNF | C | どこで使えるか | ||
EVTEST_HST | H | どこで使えるか | ||
EVTEST_ENV_CNF | E | C | どちらの値が見えるのか | |
EVTEST_ENV_HST | E | H | どちらの値が見えるのか | |
EVTEST_CNF_HST | C | H | どちらの値が見えるのか |
※1 NEXT_PUBLIC_EVTEST_ENV
のように NEXT_PUBLIC_
をつけたものも用意します。
値の設定方法
### .envファイルでの設定
1EVTEST_ENV=E2EVTEST_ENV_CNF=E3EVTEST_ENV_HST=E4NEXT_PUBLIC_EVTEST_ENV=E5NEXT_PUBLIC_EVTEST_ENV_CNF=E6NEXT_PUBLIC_EVTEST_ENV_HST=E
### next.config.js (next.config.ts) での設定
1const nextConfig: NextConfig = {2 env: {3 EVTEST_CNF: "C",4 EVTEST_ENV_CNF: "C",5 EVTEST_CNF_HST: "C",6 NEXT_PUBLIC_EVTEST_CNF: "C",7 NEXT_PUBLIC_EVTEST_ENV_CNF: "C",8 NEXT_PUBLIC_EVTEST_CNF_HST: "C",9 // 以下はここで中継してみるテストです。10 EVTEST_ENV2: process.env.EVTEST_ENV,11 EVTEST_CNF2: process.env.EVTEST_CNF,12 EVTEST_HST2: process.env.EVTEST_HST,13 EVTEST_ENV_CNF2: process.env.EVTEST_ENV_CNF,14 EVTEST_ENV_HST2: process.env.EVTEST_ENV_HST,15 EVTEST_CNF_HST2: process.env.EVTEST_CNF_HST,16 NEXT_PUBLIC_EVTEST_ENV2: process.env.NEXT_PUBLIC_EVTEST_ENV,17 NEXT_PUBLIC_EVTEST_CNF2: process.env.NEXT_PUBLIC_EVTEST_CNF,18 NEXT_PUBLIC_EVTEST_HST2: process.env.NEXT_PUBLIC_EVTEST_HST,19 NEXT_PUBLIC_EVTEST_ENV_CNF2: process.env.NEXT_PUBLIC_EVTEST_ENV_CNF,20 NEXT_PUBLIC_EVTEST_ENV_HST2: process.env.NEXT_PUBLIC_EVTEST_ENV_HST,21 NEXT_PUBLIC_EVTEST_CNF_HST2: process.env.NEXT_PUBLIC_EVTEST_CNF_HST,22 },23};
### Vercelの設定画面での設定

### Cloud Runの設定画面での設定

### Amplifyの設定画面での設定

### Netlifyの設定画面での設定

(Xenv,Xconf,Xhost) の設定に対して、以下のタイミングで値を確認します。
- Ymid Middleware処理時
- Yssr このページのSSR処理時
- Yroute /2024/nextjs-env/api/route.ts の処理時
- Yclient このページのクライアント処理時
値の確認方法
まず以下の関数を用意しました。
1export const listEnvTestEntries = function* (): Generator<[string, string | undefined]> {2 yield ["EVTEST_ENV", process.env.EVTEST_ENV];3 yield ["EVTEST_CNF", process.env.EVTEST_CNF];4 yield ["EVTEST_HST", process.env.EVTEST_HST];5 yield ["EVTEST_ENV_CNF", process.env.EVTEST_ENV_CNF];6 yield ["EVTEST_ENV_HST", process.env.EVTEST_ENV_HST];7 yield ["EVTEST_CNF_HST", process.env.EVTEST_CNF_HST];8 yield ["NEXT_PUBLIC_EVTEST_ENV", process.env.NEXT_PUBLIC_EVTEST_ENV];9 yield ["NEXT_PUBLIC_EVTEST_CNF", process.env.NEXT_PUBLIC_EVTEST_CNF];10 yield ["NEXT_PUBLIC_EVTEST_HST", process.env.NEXT_PUBLIC_EVTEST_HST];11 yield ["NEXT_PUBLIC_EVTEST_ENV_CNF", process.env.NEXT_PUBLIC_EVTEST_ENV_CNF];12 yield ["NEXT_PUBLIC_EVTEST_ENV_HST", process.env.NEXT_PUBLIC_EVTEST_ENV_HST];13 yield ["NEXT_PUBLIC_EVTEST_CNF_HST", process.env.NEXT_PUBLIC_EVTEST_CNF_HST];14 yield ["EVTEST_ENV2", process.env.EVTEST_ENV2];15 yield ["EVTEST_CNF2", process.env.EVTEST_CNF2];16 yield ["EVTEST_HST2", process.env.EVTEST_HST2];17 yield ["EVTEST_ENV_CNF2", process.env.EVTEST_ENV_CNF2];18 yield ["EVTEST_ENV_HST2", process.env.EVTEST_ENV_HST2];19 yield ["EVTEST_CNF_HST2", process.env.EVTEST_CNF_HST2];20 yield ["NEXT_PUBLIC_EVTEST_ENV2", process.env.NEXT_PUBLIC_EVTEST_ENV2];21 yield ["NEXT_PUBLIC_EVTEST_CNF2", process.env.NEXT_PUBLIC_EVTEST_CNF2];22 yield ["NEXT_PUBLIC_EVTEST_HST2", process.env.NEXT_PUBLIC_EVTEST_HST2];23 yield ["NEXT_PUBLIC_EVTEST_ENV_CNF2", process.env.NEXT_PUBLIC_EVTEST_ENV_CNF2];24 yield ["NEXT_PUBLIC_EVTEST_ENV_HST2", process.env.NEXT_PUBLIC_EVTEST_ENV_HST2];25 yield ["NEXT_PUBLIC_EVTEST_CNF_HST2", process.env.NEXT_PUBLIC_EVTEST_CNF_HST2];26};
### Middleware処理時
middleware.tsで /envtest へのリクエストに上記関数の結果を返すようにします。このページでの結果は以下の通りです。
### このページのSSR処理時
SSRなコンポーネントで上記関数の結果を返すようにします。
1import { listEnvTestEntries } from "./path/to/listEnvTestEntries";2import { EnvTestData } from "./EnvTestData";3export const EnvTestSsr = () => (4 <EnvTestData data={[...listEnvTestEntries()]} columnName="SSR" />5);
EnvTestData
はEVTEST_ENV=env
のように変数名とその値を1行ずつ出力します。このページでの結果は以下の通りです。
EVTEST_ENV=E EVTEST_CNF=C EVTEST_HST=H EVTEST_ENV_CNF=C EVTEST_ENV_HST=H EVTEST_CNF_HST=C NEXT_PUBLIC_EVTEST_ENV=E NEXT_PUBLIC_EVTEST_CNF=C NEXT_PUBLIC_EVTEST_HST=H NEXT_PUBLIC_EVTEST_ENV_CNF=C NEXT_PUBLIC_EVTEST_ENV_HST=H NEXT_PUBLIC_EVTEST_CNF_HST=C EVTEST_ENV2=E EVTEST_CNF2= EVTEST_HST2=H EVTEST_ENV_CNF2=E EVTEST_ENV_HST2=H EVTEST_CNF_HST2=H NEXT_PUBLIC_EVTEST_ENV2=E NEXT_PUBLIC_EVTEST_CNF2= NEXT_PUBLIC_EVTEST_HST2=H NEXT_PUBLIC_EVTEST_ENV_CNF2=E NEXT_PUBLIC_EVTEST_ENV_HST2=H NEXT_PUBLIC_EVTEST_CNF_HST2=H
### /2024/nextjs-env/api/route.ts の処理時
SSRと同じ結果と予想したのですが、念のため用意しました。
1import { NextResponse } from "next/server";2import { listEnvTestEntries } from "./path/to/listEnvTestEntries";3export const GET = () => NextResponse.json([...listEnvTestEntries()]);
このページでの結果は以下の通りです。
### このページのクライアント処理時
EnvTestSsr.tsx を "use client" にしたものです。Hydrationを避けるためuseEffect内で値を取得しています。
1"use client";2import { useEffect, useState } from "react";3import { listEnvTestEntries } from "./path/to/listEnvTestEntries";4import { EnvTestData } from "./EnvTestData";5export const EnvTestClient = () => {6 const [data, setData] = useState<Array<[string, string | undefined]>>([]);7 useEffect(() => setData([...listEnvTestEntries()]), []);8 return <EnvTestData data={data} columnName="Client" />;9};
このページでの結果は以下の通りです。
## 2024年12月15日の結果
public は NEXT_PUBLIC_
をつけた場合です。後半は next.config.js
で中継した場合です。
Xenv
Xconf
Xhost
Ymid
Yssr
Yroute
Yclient
環境変数の設定
Xenv
Xconf
Xhost
1.removeEremoveremove
2.removeremoveCremove
3.removeremoveremoveH
4.removeECremove
5.removeEremoveH
6.removeremoveCH
7.publicEremoveremove
8.publicremoveCremove
9.publicremoveremoveH
10.publicECremove
11.publicEremoveH
12.publicremoveCH
13.removeEremoveremove
14.removeremoveCremove
15.removeremoveremoveH
16.removeECremove
17.removeEremoveH
18.removeremoveCH
19.publicEremoveremove
20.publicremoveCremove
21.publicremoveremoveH
22.publicECremove
23.publicEremoveH
24.publicremoveCH
Ymiddle
E
C
H
C
H
C
E
C
H
C
E
C
E
E
E
E
E
E
Yserver
E
C
C
E
C
E
C
C
E
C
E
E
E
E
E
E
Yroute
E
C
H
C
H
C
E
C
H
C
E
C
E
E
E
E
E
E
Yclient
C
C
C
E
C
C
E
C
E
E
E
E
E
E
Cloud Run
Ymiddle
E
C
C
E
C
E
C
H
C
H
C
E
H
E
H
H
E
H
E
H
H
Yserver
E
C
H
C
H
C
E
C
H
C
H
C
E
H
E
H
H
E
H
E
H
H
Yroute
E
C
C
E
C
E
C
H
C
H
C
E
H
E
H
H
E
H
E
H
H
Yclient
C
C
C
E
C
H
C
H
C
E
H
E
H
H
E
H
E
H
H
Amplify
Ymiddle
C
H
C
H
C
E
C
H
C
H
C
E
H
E
H
H
E
H
E
H
H
Yserver
E
C
H
C
H
C
E
C
H
C
H
C
E
H
E
H
H
E
H
E
H
H
Yroute
E
C
H
C
H
C
E
C
H
C
H
C
E
H
E
H
H
E
H
E
H
H
Yclient
C
C
C
E
C
H
C
H
C
E
H
E
H
H
E
H
E
H
H
Netlify
Ymiddle
C
H
C
H
C
E
C
H
C
H
C
E
H
E
H
H
E
H
E
H
H
Yserver
E
C
H
C
H
C
E
C
H
C
H
C
E
H
E
H
H
E
H
E
H
H
Yroute
E
C
H
C
H
C
E
C
H
C
H
C
E
H
E
H
H
E
H
E
H
H
Yclient
C
C
C
E
C
H
C
H
C
E
H
E
H
H
E
H
E
H
H
Vercel
- .envで設定した環境変数はどこで使えるのか (1, 7, 13, 19行目)
- サーバーで使える。
NEXT_PUBLIC_
がついていればクライアントでも使える。 - Cloud RunとAmplifyではMiddlewareでも使える。
- VercelとNetlifyのMiddlewareでは使えない。
NEXT_PUBLIC_
がついていれば使える。
- サーバーで使える。
- next.config.jsで設定した環境変数はどこで使えるのか (2, 8, 14, 20行目)
- どこでも使える。
NEXT_PUBLIC_
がついていなくてもクライアントで使える。
- どこでも使える。
- Cloud Runで設定した環境変数はどこで使えるのか (3, 9行目)
- middlewareとrouteで使える。
NEXT_PUBLIC_
がついていてもクライアントでは使えない。
- middlewareとrouteで使える。
- Amplifyで設定した環境変数はどこで使えるのか (3, 9行目)
- SSR時に使える。
NEXT_PUBLIC_
がついていれば使える。 - next.config.jsで中継するとどこでも使える。
- SSR時に使える。
- Netlify, Vercelで設定した環境変数はどこで使えるのか (3, 9行目)
- クライアント以外で使える。
NEXT_PUBLIC_
がついていればクライアントでも使える。
- クライアント以外で使える。
- Xenv と Xconf と Xhostの環境設定変数の優先順位
- (Xenv,Xconf) は Xconf が勝つ。(4行目)
- (Xenv,Xhost) は ... 5行目を見てください。
- (Xconf,Xhost) は Xconf が勝つ。(6行目)
- next.config.js で中継するとどうなるか (13-24行目)
- Cloud Runでは.envにある値以外は中継されず、既存の値も隠れてしまう。中継しない方がいい。
- Amplify, Netlify, Vercelでは中継される。クライアントでも使える。
## このページでの結果まとめ
環境変数
Ymiddle
Yserver
Yroute
Yclient
1
EVTEST_ENV
2
EVTEST_CNF
3
EVTEST_HST
4
EVTEST_ENV_CNF
5
EVTEST_ENV_HST
6
EVTEST_CNF_HST
7
NEXT_PUBLIC_EVTEST_ENV
8
NEXT_PUBLIC_EVTEST_CNF
9
NEXT_PUBLIC_EVTEST_HST
10
NEXT_PUBLIC_EVTEST_ENV_CNF
11
NEXT_PUBLIC_EVTEST_ENV_HST
12
NEXT_PUBLIC_EVTEST_CNF_HST
13
EVTEST_ENV2
14
EVTEST_CNF2
15
EVTEST_HST2
16
EVTEST_ENV_CNF2
17
EVTEST_ENV_HST2
18
EVTEST_CNF_HST2
19
NEXT_PUBLIC_EVTEST_ENV2
20
NEXT_PUBLIC_EVTEST_CNF2
21
NEXT_PUBLIC_EVTEST_HST2
22
NEXT_PUBLIC_EVTEST_ENV_CNF2
23
NEXT_PUBLIC_EVTEST_ENV_HST2
24
NEXT_PUBLIC_EVTEST_CNF_HST2
JSON
{ "Ymiddle": ",,,,,,,,,,,,,,,,,,,,,,,", "Yserver": ",,,,,,,,,,,,,,,,,,,,,,,", "Yroute": ",,,,,,,,,,,,,,,,,,,,,,,", "Yclient": ",,,,,,,,,,,,,,,,,,,,,,," }
以上です。MiddlewareからOpenTelemetryでログを送るところはまた別の記事で書きます。