serverRuntimeConfigとpublicRuntimeConfigの違いを調べてみたのでメモしておきます。
Server Componentsでは呼び出せましたが、そもそも廃止されているようなので、代わりの方法も検討します。

serverRuntimeConfigとpublicRuntimeConfigの違い

サーバー側だけで使うものserverRuntimeConfig、クライアント側とサーバー側で使うものpublicRuntimeConfigなのですが。。。

設定して出力してみる(Server Components)

next.config.js

const nextConfig = {
  reactStrictMode: true,
+  serverRuntimeConfig: {
+    // Will only be available on the server side
+    serverConfig: 'server'
+  },
+  publicRuntimeConfig: {
+    // Will be available on both server and client
+    publicConfig: 'public'
+  }
}

src/app/[locale]/components/Infomations.tsx

+ import getConfig from 'next/config'

+ const { publicRuntimeConfig, serverRuntimeConfig } = getConfig()
+ console.log(publicRuntimeConfig, serverRuntimeConfig)
+ const config = getConfig()
+ console.log(config)

ターミナル

{ publicConfig: 'public' } { serverConfig: 'server' }
{
  configFileName: 'next.config.js',
  publicRuntimeConfig: { publicConfig: 'public' },
  serverRuntimeConfig: { serverConfig: 'server' }
}

Client Componentsで出力してみる

src/app/[locale]/components/Infomations.tsx

+ 'use client'
Unhandled Runtime Error
TypeError: Cannot destructure property 'publicRuntimeConfig' of
 'next_config__WEBPACK_IMPORTED_MODULE_2___default(...)(...)' as it is undefined.

> 11 | const { publicRuntimeConfig, serverRuntimeConfig } = getConfig()
     |        ^

serverRuntimeConfigだけでなく、publicRuntimeConfigも呼べない。

src/app/[locale]/components/Infomations.tsx

- const { publicRuntimeConfig, serverRuntimeConfig } = getConfig()
- console.log(publicRuntimeConfig, serverRuntimeConfig)

ターミナル

{
  serverRuntimeConfig: { serverConfig: 'server' },
  publicRuntimeConfig: { publicConfig: 'public' }
}

ブラウザのコンソール

undefined

Client Componentsからは取得できない。

Server Componentsから渡してあげる

Server Components: src/app/[locale]/page.tsx

+ import getConfig from 'next/config'

+ const { publicRuntimeConfig, serverRuntimeConfig } = getConfig()

  return (

-          <Infomations />
+          <Infomations publicConfig={publicRuntimeConfig.publicConfig} serverConfig={serverRuntimeConfig.serverConfig} />

Client Components: src/app/[locale]/components/Infomations.tsx

+ 'use client'

- export default function Infomations() {
+ export default function Infomations({ publicConfig, serverConfig }: { publicConfig: any, serverConfig: any }) {

  return (

+            publicConfig: {publicConfig}<br/>
+            serverConfig: {serverConfig}
publicConfig: public
serverConfig: server

やっぱり、両方出てしまう。。。

この機能は廃止されました

next.config.js Options: Runtime Config | Next.js

Warning:
  This feature is deprecated. We recommend using environment variables instead,
   which also can support reading runtime values.
  この機能は廃止されました。代わりに、ランタイム値の読み取りもサポートできる
   環境変数を使用することをお勧めします。

選択肢と方針

Configuring: Environment Variables | Next.js

.envでNEXT_PUBLIC_を付けると、Client Componentsからも参照できる

.env.development, .env.productionで環境毎の情報が持てる。
→ 環境毎に異なる値(APIドメイン等)は、コンテナの環境変数や.bashrcで設定したのを使うので、.env.developmentを使う。
→ 環境で変わらない値(APIのURI等)は、変更出来ない方がいいので.envじゃない方法にしたい。

.env.local, .env.development.local, .env.production.localは、デフォルトではGitから除外されていて、シークレットな値を入れる想定。
→ AWSならParameter StoreかSecrets Managerを使うので不要。

next.config.js Options: env | Next.js

next.config.jsでenvを定義できる
→ .envに書かなくても、process.envで取得できる。

上記と同様に、Client Componentsからも参照するには、NEXT_PUBLIC_を付ける必要がある。

stringしか設定できない。booleanやnumberは、ts(2322)の警告が出る。
→ .envから取得できるのもstring(ECSの環境変数も文字列)なので、.envを使うのと変わらない。

config.tsを作って、importして使う

実装するので自由度が高い。やりたい事。
・.envの値の型を変えたい
・.env未設定時、デフォルト値で上書きしたい
・.envで変更できない値を持ちたい。
・objectも持てる。

方針に従って修正

.env → .env.development

コンテナの環境変数や.bashrcで設定するので、ローカルだけになるようにファイル名を変更。
Client Componentsからも参照できるように、NEXT_PUBLIC_を追加。

- SERVER_ENV=development  # or test or staging or production
+ NEXT_PUBLIC_SERVER_ENV='development'  # or test or staging or production
+ NEXT_PUBLIC_DEBUG=true

src/config.ts

i18n対応で、同名のを使っていたので、そちらをsrc/i18n.config.tsに変更してから作成。

export const config = {
  serverEnv: process.env.NEXT_PUBLIC_SERVER_ENV || 'production',
  debug: process.env.NEXT_PUBLIC_DEBUG === 'true'
}

src/app/[locale]/layout.tsx

+ import { config } from '@/config'

-      template: `%s - ${t('app_name')}${t(`env_name.${process.env.SERVER_ENV || 'production'}`)}`
+      template: `%s - ${t('app_name')}${t(`env_name.${config.serverEnv}`)}`

-                <Link href="/">{`${t('app_name')}${t('sub_title')}${t(`env_name.${process.env.SERVER_ENV || 'production'}`)}`}</Link>
+                <Link href="/">{`${t('app_name')}${t('sub_title')}${t(`env_name.${config.serverEnv}`)}`}</Link>

src/app/[locale]/page.tsx

+ import { config } from '@/config'

-      absolute: `${t('app_name')}${t(`env_name.${process.env.SERVER_ENV || 'production'}`)}`
+      absolute: `${t('app_name')}${t(`env_name.${config.serverEnv}`)}`

src/app/[locale]/components/Infomations.tsx

Client Componentsで表示されるかのテストをします。

+ 'use client'

+ import { config } from '@/config'

  return (

+            {String(config.debug)}

メモ: 文字列じゃないのを入れても表示されず、Warningが出ます。

Warning: Failed prop type: Invalid prop `children` supplied to `ForwardRef(Typography)`, expected a ReactNode.

今回のコミット内容

呼び出し(process.env → config)がスッキリして、
文字列以外の型やデフォルト値も使えるようになりました。
変更不要な設定値や、オブジェクトも簡単に入れられます。

.envを見直してconfig経由で呼び出すように変更

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です