config vs dotenv vs dotenv-expand vs dotenv-safe
Node.js アプリケーションにおける環境変数と設定管理
configdotenvdotenv-expanddotenv-safe類似パッケージ:

Node.js アプリケーションにおける環境変数と設定管理

configdotenvdotenv-expanddotenv-safe はすべて Node.js アプリケーションにおける設定管理を目的とした npm パッケージですが、アプローチが大きく異なります。config は JSON/YAML ファイルベースの階層的な設定管理を提供し、環境ごとの設定ファイルを自動でマージします。一方、dotenv.env ファイルから環境変数を process.env にロードするシンプルなライブラリです。dotenv-expanddotenv の出力を拡張し、環境変数内で他の変数を参照できるようにします。dotenv-safedotenv の上位互換で、必須環境変数を .env.example で定義し、実行時にその存在を検証します。これらのツールは単独でも、あるいは組み合わせて使うこともでき、プロジェクトの複雑さや要件に応じて選択すべきです。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
config06,426207 kB122ヶ月前MIT
dotenv020,426103 kB31ヶ月前BSD-2-Clause
dotenv-expand01,05419 kB223日前BSD-2-Clause
dotenv-safe077110.4 kB42年前MIT

Node.js アプリケーションにおける環境変数管理:config vs dotenv vs dotenv-expand vs dotenv-safe

Node.js アプリケーションでは、設定値を環境に応じて柔軟に切り替える必要があります。この課題に対処する代表的な npm パッケージとして configdotenvdotenv-expanddotenv-safe がありますが、それぞれ設計思想や用途が大きく異なります。実際の開発現場でどう使い分けるべきか、技術的観点から詳しく見ていきましょう。

📁 設定の構造と読み込み方式

config は JSON や YAML などの静的ファイルをベースに階層的な設定を提供します。環境ごとに別々の設定ファイルを用意し、アプリ起動時に自動でマージします。

// config/default.json
{
  "db": {
    "host": "localhost",
    "port": 5432
  }
}

// config/production.json
{
  "db": {
    "host": "prod-db.example.com"
  }
}

// app.js
const config = require('config');
console.log(config.get('db.host')); // 環境に応じて自動切り替え

dotenv.env ファイルから環境変数を process.env に直接ロードします。シンプルで軽量ですが、構造化された設定には向いていません。

// .env
DB_HOST=localhost
DB_PORT=5432

// app.js
require('dotenv').config();
console.log(process.env.DB_HOST); // 'localhost'

dotenv-expanddotenv の出力を拡張し、環境変数内で他の変数を参照できるようにします。

// .env
BASE_URL=http://localhost:3000
API_URL=${BASE_URL}/api

// app.js
const dotenv = require('dotenv');
const dotenvExpand = require('dotenv-expand');
const myEnv = dotenv.config();
dotenvExpand.expand(myEnv);
console.log(process.env.API_URL); // 'http://localhost:3000/api'

dotenv-safedotenv の上位互換で、必須環境変数を .env.example で定義し、実行時に存在確認を行います。

// .env.example
DB_HOST=
DB_PORT=

// .env
DB_HOST=localhost
DB_PORT=5432

// app.js
require('dotenv-safe').config({
  allowEmptyValues: true
});
// DB_HOST または DB_PORT が欠けていたらエラー

🔐 必須環境変数の保証

configconfig.has('key') でキーの存在をチェックできますが、起動時の強制検証機能はありません。

const config = require('config');
if (!config.has('requiredKey')) {
  throw new Error('requiredKey is missing');
}

dotenv には必須変数の検証機能が一切ありません。開発者が自前でチェックする必要があります。

require('dotenv').config();
if (!process.env.REQUIRED_VAR) {
  throw new Error('REQUIRED_VAR is not set');
}

dotenv-expand は展開機能のみを提供するため、必須変数の検証は含まれていません。

// dotenv-expand は検証機能を持たない
const dotenv = require('dotenv');
const expand = require('dotenv-expand');
expand(dotenv.config());
// 必須変数のチェックは別途実装が必要

dotenv-safe.env.example に定義されたすべてのキーが .env に存在することを保証します。CI/CD 環境で特に有用です。

// dotenv-safe は自動で検証
require('dotenv-safe').config();
// .env.example にあるキーが不足していれば即時エラー

🧩 設定の階層化とオーバーライド

config は複数の設定ファイルを環境に応じて自動マージします。例えば default.jsonlocal.jsonproduction.json の順で上書きされます。

// config/default.json
{ "feature": { "enabled": false } }

// config/development.json
{ "feature": { "flag": "dev" } }

// 結果: { "feature": { "enabled": false, "flag": "dev" } }

dotenv は単一の .env ファイルしか読みません(明示的に複数指定しない限り)。階層的な設定はサポートされていません。

// dotenv は1ファイルのみ
require('dotenv').config(); // デフォルトは .env のみ

dotenv-expand も同様に単一ファイルが基本ですが、dotenv と組み合わせることで複数ファイル読み込みは可能(ただしマージ機能なし)。

// dotenv-expand 自体はマージ機能を持たない
const fs = require('fs');
const dotenv = require('dotenv');
const expand = require('dotenv-expand');

const envConfig = dotenv.parse(fs.readFileSync('.env.base'));
Object.assign(envConfig, dotenv.parse(fs.readFileSync('.env.local')));
expand.expand({ parsed: envConfig });

dotenv-safe も単一ファイルが基本で、階層的設定はサポートしていません。

// dotenv-safe も1ファイルがデフォルト
require('dotenv-safe').config();

🌐 実行環境との連携

configNODE_ENV を見て自動で対応する設定ファイルを読み込みます。また、custom-environment-variables.jsonprocess.env から特定の値をマッピングできます。

// config/custom-environment-variables.json
{
  "db": {
    "password": "DB_PASSWORD"
  }
}
// process.env.DB_PASSWORD が config.get('db.password') になる

dotenvpath オプションでファイルを指定できますが、環境ごとの自動切り替えはありません。

// dotenv で環境ごとのファイル指定
require('dotenv').config({
  path: `.env.${process.env.NODE_ENV}`
});

dotenv-expanddotenv-safe も同様に、環境切り替えは手動で行う必要があります。

// dotenv-safe で環境ファイル指定
require('dotenv-safe').config({
  path: `.env.${process.env.NODE_ENV}`,
  example: '.env.example'
});

🛠️ 実際の選定シナリオ

シナリオ1: 複雑な設定を持つ本番アプリケーション

複数環境(開発・ステージング・本番)で異なる設定を持ち、階層的な構造が必要な場合。

  • 最適: config
  • 理由: 環境ごとの設定ファイル自動マージ、カスタム環境変数マッピング、ネストされた設定構造をサポート

シナリオ2: シンプルな12要素アプリ

環境変数だけで完結するシンプルなアプリで、.env ファイルをローカル開発用に使いたい場合。

  • 最適: dotenv
  • 理由: 軽量で依存関係が少なく、必要最低限の機能のみを提供

シナリオ3: 環境変数内で他の変数を参照したい

例: DATABASE_URL=postgresql://${DB_USER}:${DB_PASS}@${DB_HOST} のようなケース。

  • 最適: dotenv-expand + dotenv
  • 理由: 変数展開機能により冗長な記述を避けられる

シナリオ4: CI/CD で確実に環境変数を検証したい

デプロイ時に必須環境変数が漏れていないかを保証したい場合。

  • 最適: dotenv-safe
  • 理由: .env.example に基づく必須変数チェックで人為ミスを防止

📌 まとめ表

パッケージ設定形式階層的設定必須変数検証変数展開環境自動切り替え
configJSON/YAML❌ (手動)✅ (NODE_ENV)
dotenv.env❌ (手動)
dotenv-expand.env❌ (手動)
dotenv-safe.env❌ (手動)

💡 最終的なアドバイス

  • シンプルさが最優先なら dotenv で十分です。多くの小規模プロジェクトではこれで問題ありません。
  • 変数展開が必要なら dotenv + dotenv-expand の組み合わせを使いましょう。
  • 必須変数の保証が不可欠なら dotenv-safe を選びましょう。特にチーム開発やCI環境では必須です。
  • 複雑な設定構造や環境ごとの差分管理が必要なら config が最適です。ただし、process.env 以外の設定ソースを扱うため、12要素アプリの原則とはやや距離があります。

これらのパッケージは相互排他的ではなく、組み合わせて使うことも可能です(例: dotenv-safe で必須変数を検証しつつ dotenv-expand で展開)。プロジェクトの要件に応じて、最も適したツールまたは組み合わせを選びましょう。

選び方: config vs dotenv vs dotenv-expand vs dotenv-safe

  • config:

    config を選ぶべきなのは、複数環境(開発・ステージング・本番など)で複雑な階層的設定が必要な場合です。JSON や YAML ファイルによる設定管理を好み、環境変数だけでなく静的ファイルベースの設定を活用したいプロジェクトに最適です。ただし、12要素アプリの原則に厳密に従う必要がある場合は、process.env 以外の設定ソースを使う点に注意が必要です。

  • dotenv:

    dotenv を選ぶべきなのは、シンプルな .env ファイルによる環境変数管理で十分なプロジェクトです。軽量で依存関係が少なく、ローカル開発環境で環境変数を簡単に設定したい場合に最適です。本番環境では環境変数を直接設定する前提で、開発時のみ .env を利用する典型的な12要素アプリ向けです。

  • dotenv-expand:

    dotenv-expand を選ぶべきなのは、.env ファイル内で他の環境変数を参照して値を構築したい場合です。例えば API_URL=${BASE_URL}/api のような変数展開が必要なシナリオで、dotenv 単体では実現できない柔軟性を提供します。必ず dotenv と組み合わせて使用します。

  • dotenv-safe:

    dotenv-safe を選ぶべきなのは、必須環境変数の存在を実行時に確実に検証したい場合です。特にチーム開発やCI/CD環境で、設定漏れによるデプロイ障害を防ぎたいプロジェクトに最適です。.env.example にテンプレートを定義することで、必要な環境変数を明示的に管理できます。

config のREADME

Configure your Node.js Applications

npm package Downloads Issues

Release Notes

Introduction

Node-config organizes hierarchical configurations for your app deployments.

It lets you define a set of default parameters, and extend them for different deployment environments (development, qa, staging, production, etc.).

Configurations are stored in configuration files within your application, and can be overridden and extended by environment variables, command line parameters, or external sources.

This gives your application a consistent configuration interface shared among a growing list of npm modules also using node-config.

Project Guidelines

  • Simple - Get started fast
  • Powerful - For multi-node enterprise deployment
  • Flexible - Supporting multiple config file formats
  • Lightweight - Small file and memory footprint
  • Predictable - Well tested foundation for module and app developers

Quick Start

The following examples are in JSON format, but configurations can be in other file formats.

Install in your app directory, and edit the default config file.

$ npm install config
$ mkdir config
$ vi config/default.json
{
  // Customer module configs
  "Customer": {
    "dbConfig": {
      "host": "localhost",
      "port": 5984,
      "dbName": "customers"
    },
    "credit": {
      "initialLimit": 100,
      // Set low for development
      "initialDays": 1
    }
  }
}

Edit config overrides for production deployment:

 $ vi config/production.json
{
  "Customer": {
    "dbConfig": {
      "host": "prod-db-server"
    },
    "credit": {
      "initialDays": 30
    }
  }
}

Use configs in your code:

const config = require('config');
//...
const dbConfig = config.get('Customer.dbConfig');
db.connect(dbConfig, ...);

if (config.has('optionalFeature.detail')) {
  const detail = config.get('optionalFeature.detail');
  //...
}

config.get() will throw an exception for undefined keys to help catch typos and missing values. Use config.has() to test if a configuration value is defined.

Start your app server:

$ export NODE_ENV=production
$ node my-app.js

Running in this configuration, the port and dbName elements of dbConfig will come from the default.json file, and the host element will come from the production.json override file.

TypeScript

Type declarations are published under types/ and resolved via typesVersions. Subpath typings are included for config/async, config/defer, config/parser, config/raw, and config/lib/util in addition to the main config entrypoint.

Articles

Further Information

If you still don't see what you are looking for, here are some more resources to check:

Contributors

lorenwestjdmarshallmarkstosi­Moseselliotttfmdkitzman
jfelegeleachi­M2kjosxenyoleosuncinarthanzel
leonardovillelajeremy-daley-krsimon-scherzingerBadger­Badger­Badger­Badgernsaboviccunneen
Osterjourth507tiny-rac00neheikesfgheorgheroncli
superovenairdrummingfoolwmertensXadilla­Xinsidedsbert

License

May be freely distributed under the MIT license.

Copyright (c) 2010-2026 Loren West and other contributors