Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 优化文档表达 #5290

Merged
merged 5 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 26 additions & 27 deletions site/docs/basics/app-start.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,20 @@ title: 启动自定义
order: 12
---

我们常常需要在应用启动期间进行一些初始化工作,等初始化完成后应用才可以启动成功,并开始对外提供服务。
我们常常需要在应用启动期间进行一些初始化工作,待初始化完成后,应用才可以启动成功,并开始对外提供服务。

框架提供了统一的入口文件(`app.js`)进行启动过程自定义,这个文件返回一个 Boot 类我们可以通过定义 Boot 类中的生命周期方法来执行启动应用过程中的初始化工作。
框架提供了统一的入口文件(`app.js`)进行启动过程自定义。这个文件需要返回一个 Boot 类我们可以通过定义 Boot 类中的生命周期方法来执行启动应用过程中的初始化工作。

框架提供了这些 [生命周期函数](../advanced/loader.md#life-cycles)供开发人员处理:
框架提供了以下 [生命周期函数](../advanced/loader.md#life-cycles) 供开发人员处理:
- 配置文件即将加载,这是最后动态修改配置的时机(`configWillLoad`);
- 配置文件加载完成(`configDidLoad`);
- 文件加载完成(`didLoad`);
- 插件启动完毕(`willReady`);
- worker 准备就绪(`didReady`);
- 应用启动完成(`serverDidReady`);
- 应用即将关闭(`beforeClose`)。

- 配置文件即将加载,这是最后动态修改配置的时机(`configWillLoad`)
- 配置文件加载完成(`configDidLoad`)
- 文件加载完成(`didLoad`)
- 插件启动完毕(`willReady`)
- worker 准备就绪(`didReady`)
- 应用启动完成(`serverDidReady`)
- 应用即将关闭(`beforeClose`)

我们可以在 `app.js` 中定义这个 Boot 类,下面我们抽取几个在应用开发中常用的生命周期函数来举例:
我们可以在 `app.js` 中定义这个 Boot 类。下面我们抽取几个在应用开发中常用的生命周期函数为例:

```js
// app.js
Expand All @@ -27,8 +26,8 @@ class AppBootHook {
}

configWillLoad() {
// 此时 config 文件已经被读取并合并,但是还并未生效
// 这是应用层修改配置的最后时机
// 此时 config 文件已经被读取并合并,但还并未生效
// 这是应用层修改配置的最后机会
// 注意:此函数只支持同步调用

// 例如:参数中的密码是加密的,在此处进行解密
Expand All @@ -39,47 +38,47 @@ class AppBootHook {
}

async didLoad() {
// 所有的配置已经加载完毕
// 可以用来加载应用自定义的文件,启动自定义的服务
// 所有配置已经加载完毕
// 可以用来加载应用自定义的文件,启动自定义服务

// 例如:创建自定义应用的示例
// 例如:创建自定义应用的实例
this.app.queue = new Queue(this.app.config.queue);
await this.app.queue.init();

// 例如:加载自定义的目录
// 例如:加载自定义目录
this.app.loader.loadToContext(path.join(__dirname, 'app/tasks'), 'tasks', {
fieldClass: 'tasksClasses',
});
}

async willReady() {
// 所有的插件都已启动完毕,但是应用整体还未 ready
// 可以做一些数据初始化等操作,这些操作成功才会启动应用
// 所有插件已启动完毕,但应用整体尚未 ready
// 可进行数据初始化等操作,这些操作成功后才启动应用

// 例如:从数据库加载数据到内存缓存
this.app.cacheData = await this.app.model.query(QUERY_CACHE_SQL);
}

async didReady() {
// 应用已经启动完毕
// 应用已启动完毕

const ctx = await this.app.createAnonymousContext();
await ctx.service.Biz.request();
}

async serverDidReady() {
// http / https server 已启动,开始接受外部请求
// 此时可以从 app.server 拿到 server 的实例
// http/https 服务器已启动,开始接收外部请求
// 此时可以从 app.server 获取 server 实例

this.app.server.on('timeout', (socket) => {
// handle socket timeout
this.app.server.on('timeout', socket => {
// 处理 socket 超时
});
}
}

module.exports = AppBootHook;
```

**注意:在自定义生命周期函数中不建议做太耗时的操作,框架会有启动的超时检测。**
**注意:在自定义生命周期函数中,不建议进行耗时的操作,因为框架会有启动的超时检测。**

如果你的 Egg 框架的生命周期函数是旧版本的,建议你升级到类方法模式;详情请查看[升级你的生命周期事件函数](../advanced/loader-update.md)。
如果你的 Egg 框架的生命周期函数是旧版本的,建议你将其升级到类方法模式;详情请查看[升级你的生命周期事件函数](../advanced/loader-update.md)。
65 changes: 31 additions & 34 deletions site/docs/basics/config.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@ order: 4

框架提供了强大且可扩展的配置功能,可以自动合并应用、插件、框架的配置,按顺序覆盖,且可以根据环境维护不同的配置。合并后的配置可直接从 `app.config` 获取。

配置的管理有多种方案,以下列一些常见的方案
配置的管理有多种方案,以下列举一些常见的方案:

1. 使用平台管理配置,应用构建时将当前环境的配置放入包内,启动时指定该配置。但应用就无法一次构建多次部署,而且本地开发环境想使用配置会变的很麻烦。
1. 使用平台管理配置,在启动时将当前环境的配置通过环境变量传入,这是比较优雅的方式,但框架对运维的要求会比较高,需要部署平台支持,同时开发环境也有相同痛点。
1. 使用代码管理配置,在代码中添加多个环境的配置,在启动时传入当前环境的参数即可。但无法全局配置,必须修改代码。

我们选择了最后一种配置方案,**配置即代码**,配置的变更也应该经过 review 后才能发布。应用包本身是可以部署在多个环境的,只需要指定运行环境即可。
1. 使用平台管理配置,应用构建时将当前环境的配置放入包内,启动时指定该配置。但应用就无法一次构建多次部署,而且本地开发环境想使用配置会变得很麻烦。
2. 使用平台管理配置,在启动时将当前环境的配置通过环境变量传入,这是比较优雅的方式,但框架对运维的要求会比较高,需要部署平台支持,同时开发环境也有相同的痛点。
3. 使用代码管理配置,在代码中添加多个环境的配置,在启动时传入当前环境的参数即可。但无法全局配置,必须修改代码。

我们选择了最后一种配置方案,**配置即代码**,配置的变更也应该经过审核后才能发布。应用包本身是可以部署在多个环境的,只需要指定运行环境即可。
### 多环境配置

框架支持根据环境来加载配置,定义多个环境的配置文件,具体环境请查看[运行环境配置](./env.md)
框架支持根据环境来加载配置,定义多个环境的配置文件,具体环境请查看[运行环境配置](./env.md)

```
config
Expand All @@ -27,11 +26,10 @@ config

`config.default.js` 为默认的配置文件,所有环境都会加载这个配置文件,一般也会作为开发环境的默认配置文件。

当指定 env 时会同时加载默认配置和对应的配置(具名配置)文件,具名配置和默认配置将合并(使用[extend2](https://www.npmjs.com/package/extend2)深拷贝)成最终配置,具名配置项会覆盖默认配置文件的同名配置。如 `prod` 环境会加载 `config.prod.js` 和 `config.default.js` 文件,`config.prod.js` 会覆盖 `config.default.js` 的同名配置。

当指定 `env` 时,会同时加载默认配置和对应的配置(具名配置)文件。具名配置和默认配置将合并(使用 [extend2](https://www.npmjs.com/package/extend2) 深拷贝)成最终配置,具名配置项会覆盖默认配置文件的同名配置。例如,`prod` 环境会加载 `config.prod.js` 和 `config.default.js` 文件,`config.prod.js` 会覆盖 `config.default.js` 的同名配置。
### 配置写法

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

```js
// 配置 logger 文件的目录,logger 默认配置由框架提供
Expand All @@ -42,7 +40,7 @@ module.exports = {
};
```

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

```js
exports.keys = 'my-cookie-secret-key';
Expand All @@ -51,7 +49,7 @@ exports.logger = {
};
```

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

```js
// 将 logger 目录放到代码目录下
Expand All @@ -65,22 +63,22 @@ module.exports = (appInfo) => {
};
```

内置的 appInfo
内置的 `appInfo` 属性包括:

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

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

请根据具体场合选择合适的写法,但请确保没有写出以下代码
请根据具体场合选择合适的写法。但请确保没有完成以下代码

```js
// config/config.default.js
// 配置文件 config/config.default.js
exports.someKeys = 'abc';
module.exports = (appInfo) => {
const config = {};
Expand All @@ -91,9 +89,9 @@ module.exports = (appInfo) => {

### 配置加载顺序

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

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

```
-> 插件 config.default.js
Expand All @@ -104,11 +102,10 @@ module.exports = (appInfo) => {
-> 应用 config.prod.js
```

**注意:插件之间也会有加载顺序,但大致顺序类似,具体逻辑可[查看加载器](../advanced/loader.md)。**

**注意**:插件之间也会有加载顺序,但大致顺序类似。具体逻辑可[查看加载器](../advanced/loader.md)。
### 合并规则

配置的合并使用 [extend2] 模块进行深度拷贝,[extend2] fork 自 [extend],处理数组时会存在差异
配置的合并使用 `extend2` 模块进行深度拷贝,`extend2` 来源于 `extend`,但是在处理数组时的表现会有所不同

```js
const a = {
Expand All @@ -125,14 +122,14 @@ extend(true, a, b);

### 配置结果

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

配置文件中会隐藏一些字段,主要包括两类:
配置文件中会隐藏以下两类字段:

- 如密码、密钥等安全字段,这里可以通过 `config.dump.ignore` 配置,必须是 [Set] 类型,查看[默认配置](https://github.com/eggjs/egg/blob/master/config/config.default.js)。
- 如函数、Buffer 等类型,`JSON.stringify` 后的内容特别大
1. 安全字段,如密码、密钥等。这些字段通过 `config.dump.ignore` 属性进行配置,其类型必须是 [Set]。可参见[默认配置](https://github.com/eggjs/egg/blob/master/config/config.default.js)。
2. 非字符串化字段,如函数、Buffer 等。这些字段在 `JSON.stringify` 后所生成的内容容量很大。

还会生成 `run/application_config_meta.json`(worker 进程)和 `run/agent_config_meta.json`(agent 进程)文件,用来排查属性的来源,如
此外,框架还会生成 `run/application_config_meta.json`(worker 进程)和 `run/agent_config_meta.json`(agent 进程)文件。这些文件用于排查配置属性的来源,例如:

```json
{
Expand All @@ -142,6 +139,6 @@ extend(true, a, b);
}
```

[set]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
[Set]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
[extend]: https://github.com/justmoon/node-extend
[extend2]: https://github.com/eggjs/extend2
Loading