Skip to content

Commit

Permalink
feat: 优化中文文档表达 (#5290)
Browse files Browse the repository at this point in the history
Co-authored-by: xiaofeng.mxf <[email protected]>
  • Loading branch information
ottomao and xiaofeng.mxf authored Jan 24, 2024
1 parent af2e543 commit d73046b
Show file tree
Hide file tree
Showing 12 changed files with 641 additions and 691 deletions.
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:/eggjs/egg/blob/master/config/config.default.js)
- 如函数、Buffer 等类型,`JSON.stringify` 后的内容特别大
1. 安全字段,如密码、密钥等。这些字段通过 `config.dump.ignore` 属性进行配置,其类型必须是 [Set]。可参见[默认配置](https:/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:/justmoon/node-extend
[extend2]: https:/eggjs/extend2
Loading

0 comments on commit d73046b

Please sign in to comment.