🦕

Denoで環境変数を扱うときはenvとVelociraptorの組み合わせが最適かも

2021/07/18に公開

※あくまで現時点での自分のユースケースでの話であり、他のモジュールをディスっているわけではないので悪しからず…

前提:Deno DeployではDeno.readFileSync()がない

先日こんな記事を書きました。

https://zenn.dev/kawarimidoll/articles/752f74860d0d78

Deno Deployではファイルシステム関連の機能がないため、dotenvライブラリで.envを読み込むことができないという話でした。

https://deno.land/x/dotenv

上記の記事ではひとまず以下のような自作スクリプトを使う形で結論づけていました。

env.ts
export default function (envName: string) {
  const envValue = Deno.env.get(envName);

  if (!envValue) {
    throw new Error(`No token: ${envName}`);
  }

  return envValue;
}
main.ts
import env from "./env.ts";
console.log(env("SECRET_TOKEN"))

これをやってくれるライブラリが既にあったので、そちらを紹介したいと思います。

envライブラリの紹介

記事執筆時点では、Deno Third Party Modulesに一切の説明がなく、エントリーポイントのファイルしかありません。
そもそもはnpmライブラリだったものを、コードだけ公開している形のようです。
https://deno.land/x/env

npmであればprocess.envから、DenoであればDeno.envから環境変数を読むという仕様になっています。.envなどのファイルの読み込みは行いません

使用する際は、Envクラスからインスタンスを生成します。
以下のようなコードをdeps.tsに書き、そこから読み込む形が良いでしょう。

deps.ts
import { Env } from "https://deno.land/x/env@v2.2.0/env.js";
const env = new Env();
export { env }

基本的なAPIは以下のとおりです。

main.ts
import { env } from "./deps.ts"

// 環境変数を取得(存在確認をしない)
const username = env.get("USERNAME");

// 取得した環境変数がなければデフォルト値を使用する
const repository = env.get("REPOSITORY", "GitHub");
// const repository = env.get("REPOSITORY") || "GitHub";

// 環境変数が存在するか調べる
const isProduction = env.has("PRODUCTION_BUILD_ID");

// 環境変数を取得(存在しないならエラー)
const SECRET_TOKEN = env.require("SECRET_TOKEN");

他のAPIの詳細はGitHubのREADMEをご一読ください。
https://github.com/humanwhocodes/env

類似ライブラリとの比較:ファイルを読み込まない

やはり環境変数の使用には需要があるようで、以下のように複数の類似ライブラリが見つかります。スター数を見た感じでは、本記事の最初でも提示しましたが、一番上のdotenvが最も有名なようです。

これらと比較して、今回紹介したenvモジュールが異なっているのは、ファイルの読み込みを行わない点です。
前述の通り、Deno.envの内容を読み込んだり存在確認をしたりするだけのモジュールとなっています。

なぜこれがポイントになるかというと、Deno Deploy環境ではDeno.readFileSync()がないためです。
つまり、ファイルの読み込みを行うモジュールは(env系に限りませんが)すべて採用対象外となるのです。

まだDeno Deployはbeta1ですが、今後プッシュされていくことは確実でしょう。
その中で「このコードはDeno Deployでは動かせない」という制約はつけたくありません。
したがって、上記のような「ファイルを読み込む」タイプのライブラリは、今後の開発での採用優先度が下がってしまうと思われます。

読み込みはVelociraptorに任せるべし

「読み込みを行わないことが利点なのはわかった。でも読み込まないと使えないでしょ?そこはどうするの?」

という問いに対しては、最初に提示した関連記事の最後の方に載せていますが、Velociraptorを使うのが良いでしょう。

以下のように設定することで、本来の実行コードから.envの読み込みを追い出すことができ、ローカルでもDeno Deployでも環境変数を使えるようになります。

velociraptor.yml
envFile:
  - .env

scripts:
  main:
    desc: Runs main script
    cmd: main.ts
  server:
    desc: Starts local server
    cmd: deployctl run --env=.env server.ts

Velociraptorに関しては以下の記事で紹介していますのでご覧ください。

https://zenn.dev/kawarimidoll/articles/b6570176eaaaea

おわりに

Deno Deployでファイルが読み込めない!ということで、最初は、「Deno.env.get()してエラー確認してデフォルト値も反映させて…」といった機能を自作しようかと考えていたのですが、既に便利なライブラリが存在していました。
自分で考える必要がなかったといえばそれまでなのですが、一度考えたおかげでコードの理解が楽に感じました。

Denoエコシステムはまだまだ発展途上なので、今後も仕様が変わっていくかもしれませんが、だからこそ楽しんでウォッチしていきたいと思います。

Discussion