🥬

Next.jsで環境変数を使用する

2024/06/02に公開

はじめに

Next.js歴数日のフロントエンド初心者です。
APIキーなどを管理する際に環境変数を定義しましたが、呼び出し方で少し苦労したのでまとめておきます。

実装

環境変数の準備

まずは環境変数を用意していきます。
.env.localファイルをNextのプロジェクト直下に作成してください

Nextのプロジェクト/
├── .next
├── node_modules
├── public
├── .env.local <-プロジェクト直下に作成
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

ファイルに以下のように記述します(例)。

.env.local
API_KEY=apikey
DOMAIN_NAME=https://hoge.hoge

これで環境変数の準備は完了です。

環境変数を呼び出す

次に環境変数をpage.tsxから呼び出してみます。
以下のコードはリンクへアクセス時に環境変数を読み取って表示するコードです。

page.tsx
import styles from "../page.module.css";

export default function Home() {
  const domain=process.env.DOMAIN_NAME
  return (
    <main className={styles.main}>
      <a>{domain}</a>
    </main>
  );
}

このコードを使用すると画面に.env.localファイルに記述したDOMAIN_NAMEが表示されると思います。
これだけで環境変数を呼び出すことはできました。
次にクライアントサイドから呼び出してみましょう。
こちらもリンクへアクセスすると環境変数を読み取って表示するコードです。

page.tsx
"use client"
import { useEffect, useState } from "react";
import styles from "../page.module.css";

export default function Home() {
  const [domain, setDomain] = useState('');
  useEffect(() => {
    const domain = `${process.env.DOMAIN_NAME}`;
    if (domain) {
      setDomain(domain);
    }
  }, []); 
  return (
    <main className={styles.main}>
      <a>{domain}</a>
    </main>
  );
}

おや?
結果がundefinedになってしまいました。
次はこの対策をしていきましょう。

クライアントサイドでも環境変数を呼び出せるようにする

.env.localを編集します。
環境変数名の前にNEXT_PUBLIC_をつけてあげましょう。

.env.local
API_KEY=apikey
NEXT_PUBLIC_DOMAIN_NAME=https:hoge.hoge

呼び出す側もNEXT_PUBLIC_を付け足して...

page.tsx
"use client"
import { useEffect, useState } from "react";
import styles from "../page.module.css";

export default function Home() {
  const [domain, setDomain] = useState('');
  useEffect(() => {
    const domain = `${process.env.NEXT_PUBLIC_DOMAIN_NAME}`;
    if (domain) {
      setDomain(domain);
    }
  }, []); 
  return (
    <main className={styles.main}>
      <a>{domain}</a>
    </main>
  );
}

これでクライアントサイドでも環境変数を呼び出すことができました。
ただこの方法一つ問題があります。
NEXT_PUBLIC_接頭辞を付けた環境変数は、ビルド時に変数値をJavaScriptにインライン化してくれるらしいので環境変数をブラウザのデベロッパーツールなどでみられる可能性があります。
https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables#:~:text=This will tell,to the browser
API_KEYなどの絶対に見られたらまずい情報はクライアントサイドで呼び出さない方が良いでしょう。

それでもクライアントサイドで使いたい!!

しかしクライアントサイドからAPIを叩きたい場面などは多く存在すると思います。
その際にはNext.js側で中継APIを作成することでクライアントサイドにAPI_KEYを直接渡さずに目的のAPIからレスポンスを得ることができました。

まずNext側でAPIを作成します。

Nextのプロジェクト/
├── .next
├── node_modules
├── public
├── .env.local <-プロジェクト直下に作成
├── src/
│   └── app/
│       ├── page.tsx
│       ├── ~ 省略~
│       └── api/
│           └── connectapi/
│               └── route.ts
├── ~省略~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

appディレクトリ内にapi/connectapiディレクトリを作成しroute.tsを作成します。
この場合APIのエンドポイントは/api/connectapiとなります。
次にroute.tsを編集していきます。

route.ts
import { NextResponse } from "next/server";

export async function GET(): Promise<NextResponse> {
    const domain=process.env.DOMAIN_NAME
    return new NextResponse(domain, { status: 200 });
}

route.tsはサーバーサイドの処理なのでprocess.env.DOMAIN_NAMEをそのまま使用することができます。
次にクライアントサイドのコードを編集していきます。

page.tsx
"use client"
import { useEffect, useState } from "react";
import styles from "../page.module.css";

export default function Home() {
  const [domain, setDomain] = useState('');
  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('/api/connect'); // APIのエンドポイントを指定
        if (!response.ok) {
          throw new Error('Failed to fetch data');
        }
        const data = await response.text();
        console.log(data)
        setDomain(data);
      } catch (error) {
        console.error('Error fetching data:', error);
      }
    };

    // fetchData関数を呼び出してAPIを叩く
    fetchData();
  }, []); 
  return (
    <main className={styles.main}>
      <a>{domain}</a>
    </main>
  );
}

先ほど作成したAPIを叩くだけです。
これでクライアントサイドでもhttps://hoge.hogeが表示されたと思います。
API_KEY等のプライベートなデータを扱うAPIはNextでのAPIの中で叩いて返ってきたレスポンスをNextでのAPIのレスポンスでそのまま返してあげればクライアント側にAPI_KEYを渡さずにAPIのレスポンスを得ることができます。

おわりに

サーバサイドレンダリングやクライアントサイドレンダリング等の概念を完璧に理解はしていないですが、これからもちまちまフロントを触ることはありそうなので備忘録として記事にしました。
誰かの役に立ったのなら幸いです。

おまけ

Next.jsのデプロイ先はVercelの場合が多いと思うのでVercelでの環境変数の使い方も書いておきます。
デプロイするコードは今回の記事のやつで大丈夫です。

Vercelでの環境変数

VercelのデプロイにはプロジェクトをGitHubにあげる必要があります。その際に.env.localファイルもあげてしまっては本末転倒です。
そのためVercel側で設定する方法があります。
まずVercelからプロジェクトを開きSettingsタブを選択します。

Environment Variablesを選択する

KeyValueを書く(環境変数と一緒)

③Saveボタンを押す

これだけでOKです。
デプロイ後も環境変数が使えるようになりました。
一つ注意点としては.env.localでは特殊文字はエスケープする必要がありましたが、Vercelの方だとそのまま書いていいみたいです。
\がそのまま反映されていてエラーの原因になっていました(一敗)

Discussion