🌲

Deno Deployとローカル開発環境でdotenvを使う

2022/12/14に公開

2022年 Deno Advent Calendar 13日目の記事です。(しまった日付を間違えていた...)

Deno Deployとローカル開発環境で併せてdotenvを使う方法をご紹介します。🦕

モチベーション

1. ローカル開発環境では、.envから参照したい

  • 実行コマンドの先頭に環境変数を列挙したり、velociraptorなどのツールは使わずに済ませる。
  • ローカル開発環境での環境変数は.gitignoreされた.envファイルから参照する。

2. Deno Deploy上では、GUI上で設定した環境変数を参照したい

https://deno.com/deploy/docs/tutorial-postgres#overview

From here, you can navigate to the "Settings" -> "Environment Variable" tab via the left navigation menu. Enter "DATABASE_URL" into the "Key" field, and paste your connection string into the "Value" field. Now, press "Add". Your environment variables is now set.

の手順で設定したものを参照する。

3. ローカル開発環境とDenoDeploy上でソースコード上の条件分岐を発生させない

ローカルではdotenvを使って、Deno DeployではDeno.env.getをそのまま使うなど、環境によって開発したソースコード上の条件分岐させない。

先に結論

export * as dotenv from "https://deno.land/std@0.167.0/dotenv/mod.ts";

await dotenv.config({
  export: true,
  // .env.exampleと、.env+通常の環境変数を比較して不足がないかチェック
  safe: true, 
  example: "./path/to/.env.example",
  path: "./path/to/.env",
});

const config = Deno.env.toObject();

export const ENV = {
  DATABASE_URL: config["DATABASE_URL"],
};

ハマったこと

標準ライブラリになる前はDeno Deployでエラーが発生していた

結論の項でimportしているdotenvは標準ライブラリですが、こちらは2022.2.24に標準ライブラリになったものです。

それ以前はこちらのライブラリを使っていました。

こちらのconfig関数を使ってDeno Deployにデプロイし、アクセスログを見ると以下のエラーが出ていました。

TypeError: Deno.readFileSync is not a function
    at parseFile (https://deno.land/x/dotenv@v3.2.0/mod.ts:100:59)
    at Module.config (https://deno.land/x/dotenv@v3.2.0/mod.ts:41:18)
    at file:///src/server/src/config/environment.ts:2:23

こちらのライブラリのdotenv.configは、同期関数であり内部的にはreadFileSyncを使用しており、https://deno.com/deploy/docs/runtime-api#deno-apis によるとDeno DeployはreadFileSyncをサポートしていないことが原因でした。
同ライブラリには、configAsyncという関数があり、これを使うことで、内部的にはreadFileSyncを避け、readFileを使うので、エラーを解消できました。

逆に標準化されたライブラリでは、
configAsyncは廃止され、configSyncメソッドが導入されたようです。

つまりは命名の変化がありました。

configAsyncconfig
configconfigSync

ですので、標準ライブラリでconfigを使っておけば、特に問題なくDeno Deployを使えるということでした!

dotenvのconfig関数では、通常の環境変数を参照できない

前項で、config関数の変化を把握したものの、config関数では、通常の環境変数を参照できないようでした。
そこで、config使って環境変数の定数を作り出すことは断念し、.envを読み込みだけをさせました。

https://deno.land/std@0.167.0/dotenv/mod.ts のAuto Loadingを参考に

await dotenv.config({
  export: true
});

const config = Deno.env.toObject()

としました。

.envをexportし、参照はDeno.env.toObject()に任せています。

最後に

dotenvでは、.env.exampleを配置することで、環境変数の不足時にクラッシュさせることができたり、デフォルト値を設定できたりするので、とても便利でした。

参考

Discussion