# 配置文件管理

URL: https://caijiao.org/express/chapter9/2-env
Source: docs/express/chapter9/2-env.md
Description: 本章节将介绍如何在 Express 项目中进行配置文件管理，确保配置的统一性和灵活性。通过合理的配置管理，可以提高项目的可维护性，尤其是在多个环境（开发、测试、生产）中切换时。

在任何开发项目中，良好的配置管理是确保项目灵活性、可扩展性和易于维护的关键因素。在 Express 项目中，我们通常需要管理不同环境下的配置，如数据库连接、服务器端口、API 密钥等。通过将这些配置集中到单独的配置文件中，可以使得应用程序在不同环境下的切换更加简单和安全。

本章节将介绍如何在 Express 应用中管理和使用配置文件。

## 1. 配置管理的基本原则

在 Express 项目中，配置文件通常存储以下内容：

- **环境变量**：不同的运行环境（如开发、测试、生产）可能需要不同的配置。
- **数据库连接信息**：如数据库主机、端口、用户名、密码等。
- **服务器端口和日志设置**：如 Express 服务器监听的端口，日志级别等。
- **第三方 API 密钥和凭证**：如 Stripe、Twilio、Google Maps API 密钥等。
- **安全设置**：如 JWT 密钥、Session 密钥等。

这些配置信息最好与代码分离，存储在独立的文件或环境变量中。

## 2. 使用 `.env` 文件

### 2.1 安装 `dotenv` 库

为了管理环境变量，可以使用 `dotenv` 库，它可以加载 `.env` 文件中的配置到 `process.env` 中，使得配置项可以在应用中随时访问。

首先，安装 `dotenv` 库：

```bash
npm install dotenv
````

### 2.2 创建 `.env` 文件

在项目根目录下创建一个 `.env` 文件，并将所有的配置项写入其中：

```plaintext
# .env 文件示例

DB_HOST=localhost
DB_PORT=27017
DB_NAME=myapp
JWT_SECRET=your-secret-key
PORT=3000
```

在 `.env` 文件中，你可以定义任何需要的环境变量。这里包含了数据库连接信息、JWT 密钥和 Express 服务器的端口。

### 2.3 加载 `.env` 文件

在应用的入口文件（如 `app.js` 或 `server.js`）中，使用 `dotenv` 加载 `.env` 文件中的配置项：

```js
require('dotenv').config();

const express = require('express');
const app = express();

// 获取配置
const dbHost = process.env.DB_HOST;
const dbPort = process.env.DB_PORT;
const dbName = process.env.DB_NAME;
const jwtSecret = process.env.JWT_SECRET;
const port = process.env.PORT || 3000;

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});
```

在上面的代码中，`dotenv` 会自动加载 `.env` 文件中的变量，并将它们存储在 `process.env` 中。你可以使用 `process.env.<VARIABLE_NAME>` 来访问相应的环境变量。

## 3. 配置文件结构

为了提高配置文件的可维护性，通常需要为不同的环境（如开发、测试、生产）提供不同的配置。这可以通过创建多个配置文件，并根据环境加载不同的配置来实现。

### 3.1 使用环境区分配置

首先，我们可以创建一个 `config` 文件夹来存放不同的配置文件，如 `default.js`、`development.js`、`production.js` 等。

```plaintext
my-express-app/
├── config/
│   ├── default.js
│   ├── development.js
│   ├── production.js
│   └── test.js
└── app.js
```

### 3.2 配置文件示例

#### `config/default.js`

```js
module.exports = {
  db: {
    host: process.env.DB_HOST || 'localhost',
    port: process.env.DB_PORT || 27017,
    name: process.env.DB_NAME || 'myapp',
  },
  jwtSecret: process.env.JWT_SECRET || 'default-secret',
  port: process.env.PORT || 3000,
};
```

#### `config/development.js`

```js
module.exports = {
  db: {
    host: 'localhost',
    port: 27017,
    name: 'myapp_dev',
  },
  jwtSecret: 'dev-secret-key',
  port: 3000,
};
```

#### `config/production.js`

```js
module.exports = {
  db: {
    host: process.env.DB_HOST,
    port: process.env.DB_PORT,
    name: process.env.DB_NAME,
  },
  jwtSecret: process.env.JWT_SECRET,
  port: process.env.PORT || 80,
};
```

#### `config/test.js`

```js
module.exports = {
  db: {
    host: 'localhost',
    port: 27017,
    name: 'myapp_test',
  },
  jwtSecret: 'test-secret-key',
  port: 3001,
};
```

### 3.3 根据环境加载配置

在应用启动时，我们根据当前的环境加载对应的配置文件。可以通过 `NODE_ENV` 环境变量来判断当前的运行环境（例如 `development`、`production` 或 `test`）。

```js
const express = require('express');
const app = express();
const config = require(`./config/${process.env.NODE_ENV || 'development'}`);

const port = config.port;
const dbHost = config.db.host;
const dbPort = config.db.port;
const dbName = config.db.name;

console.log(`Connecting to database: ${dbHost}:${dbPort}/${dbName}`);

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});
```

### 3.4 设置 `NODE_ENV` 环境变量

你可以通过在启动应用时设置 `NODE_ENV` 环境变量来指定当前的运行环境。例如：

* 在开发环境中启动：

```bash
NODE_ENV=development node app.js
```

* 在生产环境中启动：

```bash
NODE_ENV=production node app.js
```

在不同的环境下，应用将自动加载不同的配置文件。

## 4. 使用配置管理工具（可选）

为了进一步优化配置管理，你可以使用如 `config`、`nconf` 等配置管理库来统一管理配置项。这些库提供了更多的功能，如配置优先级、合并配置文件等。

### 4.1 使用 `config` 库

安装 `config` 库：

```bash
npm install config
```

然后，创建一个 `config` 文件夹，并将所有环境配置文件放入其中：

```plaintext
my-express-app/
├── config/
│   ├── default.json
│   ├── development.json
│   ├── production.json
│   └── test.json
└── app.js
```

在 `default.json` 文件中添加默认配置：

```json
{
  "db": {
    "host": "localhost",
    "port": 27017,
    "name": "myapp"
  },
  "jwtSecret": "your-secret-key",
  "port": 3000
}
```

在 `app.js` 中加载配置：

```js
const config = require('config');

const port = config.get('port');
const dbHost = config.get('db.host');
const dbPort = config.get('db.port');
const dbName = config.get('db.name');

console.log(`Connecting to database: ${dbHost}:${dbPort}/${dbName}`);

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});
```

`config` 库会自动根据 `NODE_ENV` 加载对应环境的配置文件。

## 5. 总结

通过合理的配置管理，可以使 Express 应用更加灵活、安全，并易于维护。在本章节中，我们介绍了：

1. **使用 `.env` 文件**：通过 `dotenv` 库加载环境变量，并在应用中使用。
2. **按环境区分配置**：为不同环境（如开发、生产、测试）创建不同的配置文件，并根据 `NODE_ENV` 环境变量加载相应的配置。
3. **使用配置管理工具**：通过 `config` 等库管理项目的配置信息，简化配置的加载和管理。

通过这些方式，你可以在不同的环境中灵活地管理和使用配置，确保项目的高效开发与部署。
