はじめに
普段.env
ファイルを用いて環境変数の設定をしているのですが、process.env
オブジェクトで環境変数にアクセスすると型の問題や環境変数の設定漏れが実行時にしかわからない問題があったため、t3-envというOSSを使ってこの問題を解決しようと思います。
t3-envとは?
Forgetting environment variables during build can be a hassle and difficult to debug if a bug is caused by a missing environment variable. This package provides a simple way to define environment variables validation for your app.
This library does all the grunt work for you, simply define your schema and use your environment variables safely.
環境変数の設定漏れやprocess.envを使用することによる型の問題を解決するためのOSSです。Theo 氏によって開発されたT3 Stack
というWeb開発技術スタックの中の環境変数を操作する部分をOSS化したものになります。
注意事項
- bunを使っていますがパッケージマネージャーは適宜読み替えてください
- 今回は特定のフレームワークには依存せず
env-core
というパッケージを使用します- Next.jsやNuxtへの導入方法は公式ドキュメントの方で記載があります
- t3-envはESMモジュールでしか使えないのでCommonJSの人は注意が必要です
setup方法
install
zod
に依存関係があるので一緒にインストールして下さい
$ bun add @t3-oss/env-core zod
env.tsファイルの準備
t3-envを使って環境変数を一括で管理していきます。こちらのファイルに書いてある環境変数が.env
ファイル等から取得できない場合に、例外が起きるようになります。
# env.ts
import { createEnv } from '@t3-oss/env-core';
import { z } from 'zod';
export const env = createEnv({
// フロントで動かしたい場合はclientにする
server: {
// ここに環境変数を書いていく
DATABASE_URL: z.string(),
},
runtimeEnv: process.env,
});
tsconfigの設定
env.tsを書くとTypescriptから下記のようなエラーが発生すると思います。
# env.ts
import { createEnv } from '@t3-oss/env-core';
error:
Cannot find module '@t3-oss/env-core' or its corresponding type declarations.
There are types at '/workspace/node_modules/@t3-oss/env-core/dist/index.d.ts', but this result could not be resolved under your current 'moduleResolution' setting. Consider updating to 'node16', 'nodenext', or 'bundler'.ts(2307)
tsconfig.json
にpathを書いてエラーを回避していきます
# tsconfig.json
{
"compilerOptions": {
"strict": true,
// pathsを追加する
"paths": {
"@t3-oss/env-core": [
"./node_modules/@t3-oss/env-core/dist"
]
}
}
}
Linterの設定
環境変数をprocess.env
経由で取得して欲しくないのでLinterでをprocess.env
を使用した時にwarningを出すようにします
自分はbiomeを使っているのでbiome.jsonc
を編集していきます。
# biome.jsonc
{
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"nursery": {
// 厳格にしたいなら"error"にしてください
"noProcessEnv": "warn"
}
}
},
}
env.ts
だけは設定上process.env
を使う必要があるのでignoreします
# env.ts
import { createEnv } from '@t3-oss/env-core';
import { z } from 'zod';
export const env = createEnv({
server: {
DATABASE_URL: z.string(),
},
// 追加する ///////////////////////
// biome-ignore lint: noProcessEnv
runtimeEnv: process.env,
});
使い方
process.env
の代わりに先ほど作成したenv.ts
からenv
オブジェクトをimportして使用していきます。
process.env
だと型アサーションする必要があるかと思いますがt3-envはzodで型を指定済みなので型アサーションする必要はありません。また、env
オブジェクトが環境変数の情報を持っているのでIDEでの型補完が効きます。
# process.envの場合
console.log(process.env.DATABASE_URL as string) // undefinedになる可能性があるため型アサーションが必要
# t3-envのenvオブジェクトの場合
import { env } from './env';
console.log(env.DATABASE_URL) // 型アサーション必要なし
終わりに
ビルド時などに環境変数が足りない、なんてことが起こらないといいなと思ってお守り代わりに使って行きたいと思います。
参考文献