😊

pnpmでインストールしたRemixでdotenvを使う

2022/02/18に公開

追記(2022/03/02)

v1.2.3 で.env ファイルを Remix に組み込まれた dotenv が読み込むようになりました。

https://github.com/remix-run/remix/pull/2063

結論

dotenv ではなく dotenv-cli を使うと動作します。

{
  "scripts": {
    "dev": "dotenv -- remix dev"
  }
}

https://www.npmjs.com/package/dotenv-cli

以下、結論以外の話を書きます。

現状

Remix 自体には.env をサポートする機能がないため、.env ファイルで環境変数を設定したい場合は dotenv を使うよう公式ドキュメントには書かれています。

しかし、pnpm ではドキュメント通りにやっても動作せず、以下のようなエラーが出ます。

$ pnpm dev

> remix-app-template@ dev /path/to/my-remix-app
> node -r dotenv/config node_modules/.bin/remix dev

/path/to/my-remix-app/node_modules/.bin/remix:2
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
          ^^^^^^^

SyntaxError: missing ) after argument list
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1031:15)
    at Module._compile (node:internal/modules/cjs/loader:1065:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:17:47
 ERROR  Command failed with exit code 1.

これについて Issue が作成されています。

https://github.com/remix-run/remix/issues/914

コメントではdevコマンドでnode_modules/.bin/remixではなくnode_modules/@remix-run/dev/cli.jsを指定するという書き込みもあります。

実行はできますが、ブラウザでアクセスすると別のエラーが出ました。

Error: Cannot find module '@remix-run/server-runtime'

エラーの原因

確認したところ、npm/yarn と pnpm でnode_modules/.bin以下に作成されるファイルが異なるようです。

npm/yarn では#!/usr/bin/env nodeから始まる JavaScript ファイルが置かれていますが、pnpm だと#!/bin/shから始まるシェルスクリプトになっています。

Binstub (node_modules/.bin に配置されるファイル) は常にシェルスクリプトです。JavaScript ファイルへのシンボリックリンクではありません。
https://pnpm.io/ja/limitations

https://pnpm.io/ja/limitations

つまり、ドキュメントに書かれたコマンドnode -r dotenv/config node_modules/.bin/remix devでは pnpm で作成されたシェルスクリプトが node に渡されてしまっており、エラーになっていると分かります。

解決策

なんとなく「dotenv cli」とかで調べてみたら dotenv-cli が出てきて、これを使ったら動きました。

実装を読んでみると、dotenv のパース結果をprocess.envObject.assignして、--以降に渡されたコマンドをspawnしているようです。

おわります。

GitHubで編集を提案

Discussion