Next.jsで環境変数を使用する
はじめに
Next.js歴数日のフロントエンド初心者です。
APIキーなどを管理する際に環境変数を定義しましたが、呼び出し方で少し苦労したのでまとめておきます。
実装
環境変数の準備
まずは環境変数を用意していきます。
.env.local
ファイルをNextのプロジェクト直下に作成してください
Nextのプロジェクト/
├── .next
├── node_modules
├── public
├── .env.local <-プロジェクト直下に作成
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ファイルに以下のように記述します(例)。
API_KEY=apikey
DOMAIN_NAME=https://hoge.hoge
これで環境変数の準備は完了です。
環境変数を呼び出す
次に環境変数を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
が表示されると思います。
これだけで環境変数を呼び出すことはできました。
次にクライアントサイドから呼び出してみましょう。
こちらもリンクへアクセスすると環境変数を読み取って表示するコードです。
"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_
をつけてあげましょう。
API_KEY=apikey
NEXT_PUBLIC_DOMAIN_NAME=https:hoge.hoge
呼び出す側もNEXT_PUBLIC_
を付け足して...
"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にインライン化してくれるらしいので環境変数をブラウザのデベロッパーツールなどでみられる可能性があります。
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
を編集していきます。
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
をそのまま使用することができます。
次にクライアントサイドのコードを編集していきます。
"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
を選択する
①
Key
とValue
を書く(環境変数と一緒)
②③Saveボタンを押す
これだけでOKです。
デプロイ後も環境変数が使えるようになりました。
一つ注意点としては.env.local
では特殊文字はエスケープする必要がありましたが、Vercelの方だとそのまま書いていいみたいです。
\
がそのまま反映されていてエラーの原因になっていました(一敗)
Discussion