dotenvの
GitHub
リポジトリ
ーは、こちら。
GitHub - joho/godotenv: A Go port of Ruby's dotenv library (Loads environment variables from .env files)
dotenvをベースにしているdotenv-vaultというプロダクトのWebサイトを見ると、
Simplify Your Secrets | Dotenv
dotenvはNode.js以外にも存在しているようです。
GitHub - joho/godotenv: A Go port of Ruby's dotenv library (Loads environment variables from .env files)
Kotlin
GitHub - cdimascio/dotenv-kotlin: 🗝️ Dotenv is a module that loads environment variables from a .env file
Node.js
Simplify Your Secrets | Dotenv
GitHub - vlucas/phpdotenv: Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.
Python
GitHub - theskumar/python-dotenv: Reads key-value pairs from a .env file and can set them as environment variables. It helps in developing applications following the 12-factor principles.
GitHub - bkeepers/dotenv: A Ruby gem to load environment variables from `.env`.
オプションを
コマンドライン
引数で指定したり
$ node -r dotenv/config your_script.js dotenv_config_path=/custom/path/to/.env dotenv_config_debug=true
環境変数
で指定することもできるようです。
$ DOTENV_CONFIG_<OPTION>=value node -r dotenv/config your_script.js
$ DOTENV_CONFIG_ENCODING=latin1 DOTENV_CONFIG_DEBUG=true node -r dotenv/config your_script.js dotenv_config_path=/custom/path/to/.env
とりあえず、試していってみることにしましょう。
今回の環境は、こちら。
$ node --version
v18.16.1
$ npm --version
9.5.1
dotenvを使ってみる
では、dotenvを使ってみましょう。
Node.jsプロジェクトを作成。
$ npm init -y
$ npm i -D prettier
Prettierも入れています。
"devDependencies": {
"prettier": "^2.8.8"
.prettierrc.json
"singleQuote": true,
"printWidth": 120
とりあえず、環境変数を標準出力に書き出すJavaScriptを書いてみます。
print-env.js
console.log(`get env: MY_ENV_VAR = ${process.env.MY_ENV_VAR}`);
$ node print-env.js
get env: MY_ENV_VAR = undefined
この状態だと環境変数を設定していないので当然undefinedです。
環境変数を設定すれば当然ながら参照します。
$ MY_ENV_VAR=Hello node print-env.js
get env: MY_ENV_VAR = Hello
これでもいいのですが、環境変数が複数あったり使用する値を切り替えたかったりすると煩雑になってきますね。
こういう時にdotenvを使うとよいのだろうと思います。
というわけで、dotenvをインストール。
$ npm i dotenv
インストールされたdotenvのバージョン。
"dependencies": {
"dotenv": "^16.3.1"
使い方としては、まずは.envというファイルを用意するようです。
dotenv / Usage
MY_ENV_VAR=Hello from dotenv
次に、先ほどのJavaScriptファイルにdotenvのロードを追加します。
print-env.js
require('dotenv').config();
console.log(`get env: MY_ENV_VAR = ${process.env.MY_ENV_VAR}`);
これで実行すると、.envファイルに設定した内容を環境変数に追加してくれます。
$ node print-env.js
get env: MY_ENV_VAR = Hello from dotenv
明示的な追加が必要なので、dotenvをロードしている部分をコメントアウトすると
print-env.js
console.log(`get env: MY_ENV_VAR = ${process.env.MY_ENV_VAR}`);
.envファイルを読み込まなくなります。
$ node print-env.js
get env: MY_ENV_VAR = undefined
個人的にはこの「ソースコードにdotenvの使用を明示的に追加する」という方法はちょっと嫌なので、
Node.jsの--require(-r)オプションを使ったプリロードの方が良いかなと思います。
コンテナ環境とかだと、環境変数はコンテナ側の設定で行うことが多いと思いますし。
dotenv / Preload
こうすると、ソースコードにdotenvのロードを書かなくとも動作させることができます。
$ node -r dotenv/config print-env.js
get env: MY_ENV_VAR = Hello from dotenv
ちなみに、.envファイルに書かれている環境変数がすでに存在した場合は、あらかじめ環境変数として定義されている値が優先される
ようです。
$ MY_ENV_VAR=Hello node -r dotenv/config print-env.js
get env: MY_ENV_VAR = Hello
読み込むファイルを切り替える
dotenvはデフォルトで.envというファイルを読み込みますが、これを別のファイルに切り替えることができます。
こんなファイルを用意。
.env-other
MY_ENV_VAR=Hello from dotenv other
dotenvの設定は、コマンドラインオプションでdotenv_config_<option>=valueと指定するか、
環境変数でDOTENV_CONFIG_<OPTION>=valueで指定することができます。
今回は環境変数を使いましょう。読み込むファイルを.env以外にするにはDOTENV_CONFIG_PATH環境変数を指定します。
$ DOTENV_CONFIG_PATH=.env-other node -r dotenv/config print-env.js
get env: MY_ENV_VAR = Hello from dotenv other
読み込むファイルが切り替わりました。
コメントや複数行の環境変数を書く
dotenvで読み込むファイルには、コメントを書いたり、環境変数を複数行で定義できたりします。
dotenv/ Multiline values
dotenv / Comments
複数行の環境変数を定義するには、"または'で囲って複数行で書きます。コメントは#で書けばOKです。
こんな感じですね。
.env-multiple
# これは、シンプルな環境変数定義です
MY_ENV_VAR=Hello World!!
# これは、複数行の環境変数定義です
MY_ENV_MULTILINE_VAR="begin
\"クォートは\でエスケープして記述\"
読み込むソースコード。
print-env-multiple.js
console.log(`get env: MY_ENV_VAR = ${process.env.MY_ENV_VAR}`);
console.log();
console.log(`get env: MY_ENV_MULTILINE_VAR = ${process.env.MY_ENV_MULTILINE_VAR}`);
$ DOTENV_CONFIG_PATH=.env-multiple node -r dotenv/config print-env-multiple.js
get env: MY_ENV_VAR = Hello World!!
get env: MY_ENV_MULTILINE_VAR = begin
\"クォートは\でエスケープして記述\"
OKですね。
Jestと組み合わせる
最後は、dotenvをJestを組み合わせて使ってみましょう。
新しくNode.jsプロジェクトを作成。
$ npm init -y
$ npm i -D prettier
$ npm i dotenv
$ npm i -D jest
依存関係は、こんな感じになりました。
"devDependencies": {
"jest": "^29.5.0",
"prettier": "^2.8.8"
"dependencies": {
"dotenv": "^16.3.1"
scriptsはこうしておきます。
"scripts": {
"format": "prettier --write **/*.js",
"test": "jest"
.envファイルを用意。
MY_ENV_VAR=Hello dotenv
テストコード。
use-dotenv.test.js
test('use dotenv', () => {
expect(process.env.MY_ENV_VAR).toBe('Hello dotenv');
このテストはこのまま実行しても失敗します。
$ npm run test
> [email protected] test
FAIL ./use-dotenv.test.js
✕ use dotenv (4 ms)
● use dotenv
expect(received).toBe(expected) // Object.is equality
Expected: "Hello dotenv"
Received: undefined
1 | test('use dotenv', () => {
> 2 | expect(process.env.MY_ENV_VAR).toBe('Hello dotenv');
| ^
3 | });
at Object.toBe (use-dotenv.test.js:2:34)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 0.288 s, estimated 1 s
Ran all test suites.
こうすれば動作しますが、それもちょっと違う気がします…。
use-dotenv.test.js
require('dotenv').config();
test('use dotenv', () => {
expect(process.env.MY_ENV_VAR).toBe('Hello dotenv');
どうしたらいいかですが、Jestの設定ファイルでsetupFilesというものを使えば良さそうです。
Configuring Jest / setupFiles
dotenvを使う分にはでもよさそうでしたが。
Configuring Jest / setupFilesAfterEnv
jest.config.js
module.exports = {
setupFiles: ['dotenv/config'],
testEnvironment: 'node',
これでdotenvが動作するようになります。
$ npm run test
> [email protected] test
PASS ./use-dotenv.test.js
✓ use dotenv (3 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.236 s, estimated 1 s
Ran all test suites.
別のファイルを読み込ませたい場合は
.env-other
MY_ENV_VAR=Hello dotenv other
環境変数の指定をscriptsに含めればよいのかな、と。
"scripts": {
"format": "prettier --write **/*.js",
"test": "jest",
"test-other": "DOTENV_CONFIG_PATH=.env-other jest"
$ npm run test-other
> [email protected] test-other
> DOTENV_CONFIG_PATH=.env-other jest
FAIL ./use-dotenv.test.js
✕ use dotenv (4 ms)
● use dotenv
expect(received).toBe(expected) // Object.is equality
Expected: "Hello dotenv"
Received: "Hello dotenv other"
3 | test('use dotenv', () => {
> 4 | expect(process.env.MY_ENV_VAR).toBe('Hello dotenv');
| ^
5 | });
at Object.toBe (use-dotenv.test.js:4:34)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 0.251 s, estimated 1 s
Ran all test suites.
こんなところでしょうか。
最後に少しdotenvのソースコードを眺めておきます。
小さなライブラリーなので、中身を見るのもそう苦労しないでしょう。
オプションを環境変数およびコマンドラインオプションから解決している部分。
https://github.com/motdotla/dotenv/blob/v16.3.1/config.js
https://github.com/motdotla/dotenv/blob/v16.3.1/lib/env-options.js
https://github.com/motdotla/dotenv/blob/v16.3.1/lib/cli-options.js
.envファイルのパース。
https://github.com/motdotla/dotenv/blob/v16.3.1/lib/main.js#L12-L48
Node.jsで環境変数をファイルから読み込むdotenvを試してみました。
なんとなくこういうものがあるというのは知っていましたが、実際に使ったことはなかったので確認しておいてよかったです。
他の言語にも同じようなものがあることもわかりましたし。