CLOVER🍀

That was when it all began.

Node.jsで環境倉数をファむルから読み蟌むdotenvを詊す

これは、なにをしたくお曞いたもの

Node.jsで環境倉数をファむルから読み蟌むこずができるdotenvずいうものがあるらしいので、詊しおみるこずにしたした。

dotenv

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以倖にも存圚しおいるようです。

今回はNode.js向けのdotenvのみにフォヌカスしたす。

䜿い方ずしおは、.envずいうファむルを䜜成しお

.env

S3_BUCKET="YOURS3BUCKET"
SECRET_KEY="YOURSECRETKEYGOESHERE"

dotenvモゞュヌルをむンポヌトすればよいみたいです。

require('dotenv').config()
console.log(process.env) // remove this after you've confirmed it is working

あずはprocess.env.[環境倉数名]で環境倉数が参照できるようになりたす。

耇数行の蚘述もできるようです。

PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...
Kh9NV...
...
-----END RSA PRIVATE KEY-----"

--requireたたは-rオプションで、プリロヌドするこずもできるようです。

$ node -r dotenv/config your_script.js

オプションをコマンドラむン匕数で指定したり

$ 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

.env

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

// 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 = 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で読み蟌むファむルには、コメントを曞いたり、環境倉数を耇数行で定矩できたりしたす。

耇数行の環境倉数を定矩するには、"たたは'で囲っお耇数行で曞きたす。コメントは#で曞けばOKです。

こんな感じですね。

.env-multiple

# これは、シンプルな環境倉数定矩です
MY_ENV_VAR=Hello World!!

# これは、耇数行の環境倉数定矩です
MY_ENV_MULTILINE_VAR="begin

\"クォヌトは\で゚スケヌプしお蚘述\"

end"

読み蟌む゜ヌスコヌド。

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

\"クォヌトは\で゚スケヌプしお蚘述\"

end

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ファむルを甚意。

.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

> dot-env-jest-example@1.0.0 test
> jest

 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 | });
      4 |

      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

> dot-env-jest-example@1.0.0 test
> jest

 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

> dot-env-jest-example@1.0.0 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"

      2 |
      3 | test('use dotenv', () => {
    > 4 |   expect(process.env.MY_ENV_VAR).toBe('Hello dotenv');
        |                                  ^
      5 | });
      6 |

      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を詊しおみたした。

なんずなくこういうものがあるずいうのは知っおいたしたが、実際に䜿ったこずはなかったので確認しおおいおよかったです。
他の蚀語にも同じようなものがあるこずもわかりたしたし。