EggJS
Midway 可以使用 EggJS 作为上层 Web 框架,EggJS 提供了非常多常用的插件和 API,帮助用户快速构建企业级 Web 应用。本章节内容,主要介绍 EggJS 在 Midway 中如何使用自身的能力。
依赖包
针对 EggJS,Midway 提供了 @midwayjs/web
包进行了适配,在其中提供了 Midway 特有的依赖注入、切面等能力。
针对 EggJS 场景,这些包列举如下。
"dependencies": {
"@midwayjs/web": "^2.3.11",
"@midwayjs/decorator": "^2.3.11",
"egg": "^2.0.0",
"egg-scripts": "^2.10.0",
"midway": "^2.3.11"
},
"devDependencies": {
"@midwayjs/egg-ts-helper": "^1.0.1",
},
@midwayjs/web | 必须,Midway EggJS 适配层 |
---|---|
@midwayjs/decorator | 必须,Midway 系列通用的装饰器包 |
midway | 可选,Midway 启动适配包,提供了 midway v1 兼容 |
egg | 必须,EggJS 依赖包,提供定义等其他能力 |
egg-scripts | 可选,EggJS 启动脚本 |
@midwayjs/egg-ts-helper | 可选,EggJS 定义生成工具 |
和默认 EggJS 的不同之处
- 1、默认关闭 static 插件,需要时请自行开启
- 2、baseDir 默认调整为
src
目录,服务器上为dist
目录
整个架构如下:
目录结构
除了 Midway 提供的目录结构外,EggJS 还有一些特殊的目录结构(不可变),整个结构如下。
➜ my_midway_app tree
.
├── src
| ├── app.ts ## EggJS 扩展 Worker 生命周期文件(可选)
| ├── agent.ts ## EggJS 扩展 Agent 生命周期文件(可选)
| ├── app ## EggJS 固定的根目录(可选)
| │ ├── public ## EggJS 静态托管插件的默认 目录(可配)
| │ | └── reset.css
| │ ├── view (可选) ## EggJS 模板渲染的默认目录(可配)
| │ | └── home.tpl
| │ └── extend (可选) ## EggJS 扩展目录(可配)
| │ ├── helper.ts (可选)
| │ ├── request.ts (可选)
| │ ├── response.ts (可选)
| │ ├── context.ts (可选)
| │ ├── application.ts (可选)
| │ └── agent.ts (可选)
| │
| ├── config
| | ├── plugin.ts
| | ├── config.default.ts
| │ ├── config.prod.ts
| | ├── config.test.ts (可选)
| | ├── config.local.ts (可选)
| | └── config.unittest.ts (可选)
│ ├── controller ## Midway 控制器目录(推荐)
│ ├── service ## Midway 服务目录(推荐)
│ └── schedule ## Midway 定时器目录(推荐)
│
├── typings ## EggJS 定义生成目录
├── test
├── package.json
└── tsconfig.json
以上是 EggJS 的目录结构全貌,其中包含了很多 EggJS 特有的目录,有一些在 Midway 体系中已经有相应的能力替代,可以直接替换。整个结构,基本上等价于将 EggJS 的目录结构移动到了 src
目录下。
由于 EggJS 是基于约定的框架,整个工程的目录结构是固定的,这里列举一些常用的约定目录。
src/app/public/** | 用于放置静态资源,可选,具体参见内置插件 egg-static。 |
---|---|
src/config/config.{env}.ts | 用于编写配置文件,具体参见配置。 |
src/config/plugin.js | 用于配置需要加载的插件,具体参见插件。 |
test/** | 具体参见单元测试。 |
src/app.js 和 src/agent.js | 用于自定义启动时的初始化工作,可选,具体参见启动自定义。关于agent.js 的作用参见Agent 机制。 |
配置定义
Midway 在脚手架中提供了标准的 EggJS 的 TS 配置写法,其中包括了完整的定义和属性提示,结构如下。
// src/config/config.default.ts
import { EggAppConfig, EggAppInfo, PowerPartial } from 'egg';
export type DefaultConfig = PowerPartial<EggAppConfig>;
export default (appInfo: EggAppInfo) => {
const config = {} as DefaultConfig;
// use for cookie sign key, should change to your own and keep security
config.keys = appInfo.name + '_1600001669991_8079';
// add your middleware here
config.middleware = [];
config.security = {
csrf: {
enable: false,
},
};
config.sequelize = {};
return config;
};
通过这样返回方法的形式,在运行期会被自动执行,合并进完整的配置对象。
这个函数的参数为 EggAppInfo
类型,值为以下内容。
appInfo | 说明 |
---|---|
pkg | package.json |
name | 应用名,同 pkg.name |
baseDir | 应用代码的 src (本地开发)或者 dist (上线后)目录 |
appDir | 应用代码的目录 |
HOME | 用户目录,如 admin 账户为 /home/admin |
root | 应用根目录,只有在 local 和 unittest 环境下为 baseDir,其他都为 HOME。 |
注意,这里的 baseDir
和 appDir
和 EggJS 应用有所区别。
插件
插件是 EggJS 的特色之一,Midway 也支持 EggJS 的插件体系。
开启插件
插件一般通过 npm 模块的方式进行复用。
$ npm i egg-mysql --save
然后需要在应用或框架的 src/config/plugin.js
中声明开启。
如果有 export default
,请写在其中。
import { EggPlugin } from 'egg';
export default {
static: false, // default is true
mysql: {
enable: true,
package: 'egg-mysql',
},
} as EggPlugin;
如果没有 export default
,可以直接导出。
// src/config/plugin.ts
// 使用 mysql 插件
export const mysql = {
enable: true,
package: 'egg-mysql',
};
使用插件
在开启插件之后,我们就可以在业务代码中使用插件提供的功能了。一般来说,插件会将对象挂载到 EggJS 的 app
和 ctx
之上,然后直接使用。
app.mysql.query(sql, values); // egg 提供的方法
在 Midway 中可以通过 @App
获取 app
对象,以及在请求作用域中通过 @Inject() ctx
获取 ctx
对象,所以我们可以通过注入来获取插件对象。
import { Provide, Inject, Get } from '@midwayjs/decorator';
import { Application, Context } from 'egg';
@Provide()
export class HomeController {
@App()
app: Application;
@Inject()
ctx: Context;
@Get('/')
async home() {
this.app.mysql.query(sql, values); // 调用 app 上的方法(如果有的话)
this.ctx.mysql.query(sql, values); // 调用挂载在 ctx 上的方法(如果有的话)
}
}
此外,还可以通过 @Plugin
装饰器来直接注入 app