# Config

## 多环境配置

框架支持根据环境来加载配置，定义多个环境的配置

```
config
|- config.default.js
|- config.prod.js
|- config.unittest.js
`- config.local.js
```

`config.default.js`：默认的配置文件，所有环境都会加载此配置

当指定 `env` 时，会同时加载对应的加载文件，并覆盖默认配置文件的同名配置。如 `prod`  环境会加载 `config.prod.js` 和 `config.default.js` 两个配置文件，同时 `config.prod.js` 会覆盖 `config.default.js` 的同名配置

### 配置写法

配置文件返回的是一个 object 对象，可以覆盖框架的一些配置，应用也可以将自己业务的配置放到这里方便管理

```javascript
// 配置 logger 文件的目录，logger 默认配置由框架提供，也可以自定义
module.exports = {
  logger: {
    dir: '/home/admin/logs/demoapp',
  }
}
```

配置文件也可以简化的写成 `exports.key = value` 形式

```javascript
exports.keys = 'my-cookie-secret-key'
exports.logger = {
  level: 'DEBUG'
}
```

配置文件也可以返回一个 `function` ，可以接受 `appInfo` 参数

```javascript
// 将 Logger 目录放到代码目录下
const path = require('path')
module.exports = appInfo => {
  return {
    logger: {
      dir: path.join(appInfo.baseDir, 'logs'),
    }
  }
}
```

内置的 `appInfo` 有

| `appInfo` | 说明                                                        |
| :-------: | --------------------------------------------------------- |
|   `pkg`   | `package.json`                                            |
|   `name`  | 应用名，同 `pkg.name`                                          |
| `baseDir` | 应用代码的目录                                                   |
|   `HOME`  | 用户目录，如 `admin` 账户为 `/home/admin`                          |
|   `root`  | 应用根目录，只有在 `local` 和 `unittest` 环境下为 `baseDir`，其他都为 `HOME` |

`appInfo.root` 是一个优雅的适配，比如在服务器环境我们会使用 `/home/admin/logs` 作为日志目录，而本地开发时又不想污染用户目录，这样的适配就很好解决这个问题。

请根据具体场合选择合适的写法，但请确保没有写出以下代码：

```javascript
// config/config.default.js
exports.someKeys = 'abc';
module.exports = appInfo => {
  const config = {};
  config.keys = '123456';
  return config;
};
```

## 配置加载顺序

应用、插件、框架都可以定义这些配置，而且目录结构都是一致的，但存在优先级（应用 > 框架 > 插件），相对于此运行环境的优先级会更高。

比如在 prod 环境加载一个配置的加载顺序如下，后加载的会覆盖前面的同名配置。

```javascript
-> 插件 config.default.js
-> 框架 config.default.js
-> 应用 config.default.js
-> 插件 config.prod.js
-> 框架 config.prod.js
-> 应用 config.prod.js
```

&#x20;**注意：插件之间也会有加载顺序，但大致顺序类似，具体逻辑可**[**查看加载器**](https://eggjs.org/zh-cn/advanced/loader.html)**。**

## 合并规则

配置的合并使用 `extend2` 模块进行深度拷贝，`extend2` fork 自 `extend` ，处理数组时存在差异

```javascript
const a = {
  arr: [ 1, 2 ]
}

const b = {
  arr: [ 3 ]
}

extend(true, a, b)
// => { arr: [ 3 ] }
```

## 配置结果

框架在启动时会把合并后的最终配置 dump 到 `run/application_config.json`（worker 进程）和 `run/agent_config.json` （agent 进程）中，可以用来分析问题

配置文件中会隐藏一些字段，主要包括两类：

1. 如密码、密钥等安全字段，这里可以通过 `config.dump.ignore` 来配置，必须是 Set 类型，查看默认配置
2. 如函数、Buffer 等类型，`JSON.stringfy` 后的内容特别大

还会生成 `run/application_config_meta.json` （woker 进程）和 `run/agent_config_meta.json`（agent 进程）文件，用来排查属性的来源，如

```javascript
{
  "logger": {
    "dir": "/path/to/config/config.default.js"
  }
}
```
