echo("備忘録");

IT技術やプログラミング関連など、技術系の事を備忘録的にまとめています。

【Next.js】ブラウザ側で環境変数が参照できない場合の対処法

本題(今回は前置きは省略)

Next.jsで環境変数(.env.*ファイルやコンテナに設定した)をブラウザ側(クライアント側、端的にいえばReactソース上)で参照しようとしても、値が参照できない

TL;DR

内容

Next.jsで、環境変数をブラウザ側(≒クライアント側)で利用しようと思っても、そのままでは利用できません。

例えば下記ソースをブラウザで表示しても、process.env.TEST_ENV_VALUEの部分がundefinedになっているのが分かります。(stateの部分は無視してください)

#.envで環境変数を設定しても...
TEST_ENV_VALUE=hogehoge
export const ComponentDruaga: VFC<ComponentDruagaProps> = ({treasures}) => {
    const {state, changeState}: UseMyStateType = useMyState();

    return (
      <div css={myCss}>
        <div>{`stateは${state}です。`}</div>  
         // ここのprocess.env.TEST_ENV_VALUEがundefinedになっている
        <div>{`TEST_ENV_VALUEは${process.env.TEST_ENV_VALUE}です。`}</div>
        <button onClick={changeState}>stateを変える</button>
      </div>
    )
}

原因

原因ですが、Next.jsではデフォルトでブラウザ側には環境変数が公開されないからです。

ちなみに、これはれっきとしたNext.jsの仕様であり、公式ドキュメントにも明記されています。(SSRだからということもあるのかな?)

https://nextjs.org/docs/basic-features/environment-variables#exposing-environment-variables-to-the-browser

ただ、ブラウザ側でも環境変数の値を参照させたいケースは出てくると思うので、対策をする必要があります。

対策

で、対策なのですが、具体的には下記2つの方法があります。(先程の公式ドキュメント内にも記載されています)

環境変数名のプレフィックスに「NEXT_PUBLIC_」をつける

環境変数名のプレフィックスに「NEXT_PUBLIC_」をつけることで、その環境変数はブラウザ側にも公開されますので、ブラウザ側で参照することができます。

サーバーで実行される関数から環境変数を渡す

デフォルトで環境変数はサーバー側にのみ公開されるので(server-only secrets safe)、サーバー側で実行される関数から環境変数の値をpropsなどで渡してあげれば、値そのものはブラウザ側でも参照することができます。

なお「サーバーで実行される関数」には以下のものがあります。(ただし「APIルート用の関数」はAPIの呼び出しに使うもの(=APIを呼び出さないと使わない)ので、今回の目的には不向きだと思います。

  • getServerSideProps関数
  • getStaticProps関数
  • APIルート用の関数(pages/api以下)
#.envで環境変数を設定して
TEST_ENV_VALUE=hogehoge
NEXT_PUBLIC_TEST_ENV_VALUE=fugafuga
// 例えば、getServerSidePropsでこのように設定する
export const getServerSideProps: GetServerSideProps = async (context: GetServerSidePropsContext) => {
  
    return {
      props: {
        // ここで環境変数の値を設定したキーを返す
        testEnvValue: process.env.TEST_ENV_VALUE
      }
    }
}
  
// Propsには{testEnvValue: string}が設定されているものとする。
const Druaga: VFC<Props> = ({testEnvValue}) => {
    return (
      <>
        <ComponentDruaga testEnvValue={testEnvValue}/>
      </>
    )
}
  
export default Druaga
  
  
export const ComponentDruaga: VFC<Props> = ({testEnvValue}) => {
  
  const {state, changeState}: UseMyStateType = useMyState();
  
  // 下記のように環境変数の参照を変える。  
  //  (環境変数以外の部分は、無視してください)
    return (
     <div css={myCss}>
        <div>{`stateは${state}です。`}</div>
        <div>{`TEST_ENV_VALUEは${testEnvValue}です。`}</div>
        <div>{`NEXT_PUBLIC_TEST_ENV_VALUEは${process.env.NEXT_PUBLIC_TEST_ENV_VALUE}です。`}</div>
        <button onClick={changeState}>stateを変える</button>
      </div>
    )
}

上記のように変更すると、ちゃんと環境変数の値がブラウザ側でも参照できているのが分かります。

締めの言葉

ちょっと簡素ですが、今回は以上です。