App Routerで安全に環境変数を扱うならt3-envがいいよ [Next.js]

2023/05/06に公開

t3-envを使いましょう。


コメントがつくよ

環境変数にコメントをつけたり、


APIキーがないのでビルド失敗した時のエラー

欠けている環境変数に素早く気づけたり、

特にApp Routerを使う場合は要チェック。間違えてクライアントコンポーネントでサーバーの環境変数を参照した際に、エラーが出せます。

envsafeもいいのですが、1ファイルでクライアント・サーバーサイドに対応できるライブラリを知ったので共有します。

必要パッケージのインストール

https://github.com/t3-oss/t3-env

npm i @t3-oss/env-nextjs zod

あわせてzodを入れることにより、環境変数の型安全性を確保します。

https://zenn.dev/okumura_daiki/articles/6d3632c6885ed6

このライブラリは上記記事で知りました、ありがとうございます :bow:

環境変数の定義

echo MICROCMS_SERVICE_DOMAIN=ここにmicroCMSのサービスドメイン >> .env.local
echo MICROCMS_API_KEY=ここにmicroCMSのAPIキー >> .env.local

microCMSを使う場合の定義の例です。

設定ファイルの作成

t3-env用に設定ファイルを作ります。

# Next.jsのConfigがTypeScript非対応なので、importできるようmjs
touch src/env.mjs

next.config.tsが未だに書けないため、importできるようmjsで書きます。

@/env.mjs
import { createEnv } from '@t3-oss/env-nextjs';
import { z } from 'zod';

export const env = createEnv({
  server: {
    // サーバーサイド専用の環境変数のスキーマはここに定義
    /** microCMSのサービスドメイン */
    MICROCMS_SERVICE_DOMAIN: z.string(),
    /** microCMSのAPIキー */
    MICROCMS_API_KEY: z.string(),
  },
  client: {
    // クライアントサイド用の環境変数のスキーマはここに定義
    /** 1ページあたりの記事数 */
    NEXT_PUBLIC_PAGINATION_PER_PAGE: z.string(),
  },

  runtimeEnv: {
    // ここで実際の環境変数とマッピングを行う
    MICROCMS_SERVICE_DOMAIN: process.env.MICROCMS_SERVICE_DOMAIN,
    MICROCMS_API_KEY: process.env.MICROCMS_API_KEY,
    NEXT_PUBLIC_PAGINATION_PER_PAGE:
      process.env.NEXT_PUBLIC_PAGINATION_PER_PAGE,
  },
});

以下では process.envではなく、このenvから環境変数を参照してください。

next.config.js
+ import "./src/env.mjs";

/** @type {import("next").NextConfig} */
const nextConfig = {
// 後略

また、env.mjsnext.config.jsでimportして、ビルド時にバリデーションがかかるようにして下さい。(参考)

環境変数を使う

@/lib/micro-cms.ts
import { createClient } from 'microcms-js-sdk';
import { env } from '@/env.mjs';

export const microCmsClient = createClient({
  serviceDomain: env.MICROCMS_SERVICE_DOMAIN,
  apiKey: env.MICROCMS_API_KEY,
});

後はこのように環境変数を参照してください。

'use client';

import { env } from '@/env.mjs';

export default function ClientComponent() {
  return <div>1ページあたり: {env.NEXT_PUBLIC_PAGINATION_PER_PAGE}</div>;
}

クライアントコンポーネントでは NEXT_PUBLIC_ 付きだけが使えることを肝に銘じてください。

Discussion