.envファイルとConfigファイルは違う。

混同しやすいような`.env`と`config`がそれぞれある。

実際、　私自身もexpressを使って中間APIサーバー的なものを作っているときに、どういう違いで書くべきなのだろうかと思ったので自分なりにまとめる。ちなみに、laravelでも同じように使われているので、そもそもの考え方となる。


# `.env`と`config`の違い
この記事を読んでいる人が求めている答えはおそらく、「そもそも何が違うのか？」ということだと思う。
結論から言うと、「環境」か「構造」かの違いである。

- .env: environment → 環境
- Config: configuration → 構造

それでは、これらがどう違うのか？どのように使い分ければいいのか？をexpressで使うときを例に書いてみる。


## Expressでの`config.ts`と`.env`ファイルの役割と使い分け


### 1. `config.ts`ファイルの役割

`config.ts`ファイルは、アプリケーションの構成や定数を管理するために使用される。主に以下のような情報を保持することが多い。


- **アプリケーション名やバージョン**: 
アプリ名やバージョン情報は環境に依存せず、全体で一貫して使用されます。
- **デフォルト値**: 
ページネーションのデフォルト件数やUI設定など、アプリケーション全体で使用される固定の設定値。
- **固定されたAPIエンドポイント**: 
環境に関係なく使用されるAPIのエンドポイントやリソースパス。
- **UI設定**: 
テーマカラーやレイアウト設定など、見た目に関する設定。

これらの設定は環境ごとに変更されることが少なく、アプリケーションのビジネスロジックやUIに直結するものが多いため、`config.ts`で管理するのが適しているという観点で書かれる。

**例: `config.ts`ファイル**
```typescript:config.ts
const config = {
  app: {
    name: 'My Express App',
    version: '1.0.0'
  },
  ui: {
    themeColor: '#3498db'
  },
  defaultValues: {
    itemsPerPage: 10
  }
};

export default config;
```

### 2. `.env`ファイルの役割

`.env`ファイルは、環境ごとに異なる設定や機密情報を管理するために使用される。これには、開発環境、テスト環境、本番環境で異なる設定が含まれる。

- **APIキーやシークレットキー**: 
機密情報は`.env`ファイルに格納し、バージョン管理システムに含めない。
- **データベース接続情報**: 
開発・テスト・本番環境ごとに異なるデータベース接続情報。
- **環境別の設定**: 
ベースURL、ポート番号など、環境ごとに変わる設定。
- **外部サービスの認証情報**: 
AWSやGoogle APIなど、外部サービスの認証情報。

**例: `.env`ファイル**
```.env:.env
NODE_ENV=development
PORT=3000
API_KEY=your-api-key-here
DB_HOST=localhost
DB_USER=root
DB_PASS=password
```

### 3. 環境ごとの`.env`ファイルの分け方

プロジェクトが異なる環境（開発、テスト、本番）で動作する場合、それぞれの環境に応じた設定ファイルを用意することが推奨される。通常、`.env.dev`、`.env.prod`のように分けることが多い。

**例: `.env.dev`**
```.env:.env.dev
NODE_ENV=development
PORT=3000
API_KEY=dev-api-key
DB_HOST=localhost
DB_USER=dev_user
DB_PASS=dev_password
```

**例: `.env.prod`**
```.env:.env.prod
NODE_ENV=production
PORT=8000
API_KEY=prod-api-key
DB_HOST=prod-db-server
DB_USER=prod_user
DB_PASS=prod_password
```

### 4. Expressでの使い分け

Expressアプリケーションでこれらの設定を使い分ける方法を以下に書く。
まず、`dotenv`パッケージを使用して`.env`ファイルを読み込む。

**a. `dotenv`インストール:**
```bash
npm install dotenv
```

**`index.ts`での使用例:**
```typescript: index.ts
import express from 'express';
import dotenv from 'dotenv';
import config from './config';

// 環境に応じて.envファイルの読み込むこと
const env = process.env.NODE_ENV || 'development';
dotenv.config({ path: `.env.${env}` });

const app = express();
const port = process.env.PORT || 3000;

app.get('/', (req, res) => {
  res.send(`Hello from ${config.app.name}!`);
});

app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});
```

この設定により、アプリケーションを起動する際に、`NODE_ENV`に応じた`.env`ファイルが読み込まれる。たとえば、`NODE_ENV=production`でアプリケーションを起動すると、`.env.prod`が使用される。

**起動方法の例:**


```bash
NODE_ENV=production node dist/index.js
```

package.jsonのscriptに埋め込んだりとかして別の方法で起動することもで切るので調べてみてください。
→ 過去記事: 

https://qiita.com/sakenomi_dev/items/e698deef164ab2f0072b

 ## ちなみに、また別の環境という概念がある時には？

開発者が定める`.env`, `config`とはまた別の環境があることある。
例えば、ブロックチェーンでは`testnet`,`mainnet`と環境が分かれていたり、提供元からのAPIでも`ステージ`,`本番`のようになっていたりする。


### 1. `.env`ファイルの役割と使い分け
`.env`ファイルは、環境（開発・テスト・本番）ごとの設定を管理するが、ブロックチェーンのテストネットやメインネットのような「ネットワーク」の概念に対しても使用できる。ネットワークごとの設定を`.env`ファイルに含め、それに応じた設定をアプリケーションで読み込む形になる。

**例: `.env`ファイル**
**`.env.testnet`**（テストネット用の設定）
```bash: .env.testnet
NODE_ENV=development
PORT=3000
NETWORK=testnet
API_KEY=your-testnet-api-key
BLOCKCHAIN_URL=https://testnet.blockchain.api
```
  
**`.env.mainnet`**（メインネット用の設定）
```bash:.env.mainnet
NODE_ENV=production
PORT=8000
NETWORK=mainnet
API_KEY=your-mainnet-api-key
BLOCKCHAIN_URL=https://mainnet.blockchain.api
```

### 2. `config.ts`での設定とネットワークの使い分け

`config.ts`ファイルでは、`process.env`を使用して`.env`から設定を読み込み、ネットワークに応じて適切な値を設定する。また、`config.ts`でネットワーク固有の設定を含めることで、コード内で簡単にネットワークを切り替えることが可能になる。

**例: `config.ts`**

```typescript
// config.ts

const config = {
  app: {
    name: 'My Blockchain App',
    version: '1.0.0'
  },
  blockchain: {
    network: process.env.NETWORK || 'testnet',
    apiUrl: process.env.BLOCKCHAIN_URL || 'https://testnet.blockchain.api',
    apiKey: process.env.API_KEY || ''
  }
};

export default config;
```

### 3. Expressでの使い分け方

アプリケーションが起動する際に、指定された`.env`ファイルから設定を読み込み、その設定を`config.ts`に反映させる。


```typescript:index.ts
import express from 'express';
import dotenv from 'dotenv';
import config from './config';

// 環境変数に基づいて、対応する.envファイルを読み込む
const env = process.env.NETWORK || 'testnet';
dotenv.config({ path: `.env.${env}` });

const app = express();
const port = process.env.PORT || 3000;

app.get('/', (req, res) => {
  res.send(`Hello from ${config.app.name} running on ${config.blockchain.network}!`);
});

app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});
```

### 4. 実行時の設定

テストネットやメインネットでの実行を切り替える際には、以下のように`NETWORK`変数を指定してアプリケーションを起動する。

```bash
# テストネットでの実行
NETWORK=testnet node dist/index.js

# メインネットでの実行
NETWORK=mainnet node dist/index.js
```

# まとめ
おもしろい。