- 提供基于 Egg 定制上层框架的能力
- 高度可扩展的插件机制
- 内置多进程管理
- 基于 Koa 开发,性能优异
- 框架稳定,测试覆盖率高
- 渐进式开发
目录结构
├── package.json
├── app.js (app.js 和 agent.js 用于自定义启动时的初始化工作)
├── agent.js (可选)
├── app
| ├── router.js(用于配置 URL 路由规则)
│ ├── controller(用于解析用户的输入,处理后返回相应的结果)
│ | └── home.js
│ ├── service (用于编写业务逻辑层,可选)
│ | └── user.js
│ ├── middleware (用于编写中间件,可选)
│ | └── response_time.js
│ ├── schedule (用于定时任务,可选)
│ | └── my_task.js
│ ├── public (用于放置静态资源,可选)
│ | └── reset.css
│ ├── extend (用于框架的扩展,可选)
│ | └── application.js app 对象指的是 Koa 的全局应用对象,全局只有一个,在应用启动时被创建。
│ ├── context.js (Context 指的是 Koa 的请求上下文,这是 请求级别 的对象)
│ ├── request.js (Request 对象和 Koa 的 Request 对象相同,是 请求级别 的对象)
│ ├── response.js (Response 对象和 Koa 的 Response 对象相同,是 请求级别 的对象)
│ ├── helper.js (Helper 函数用来提供一些实用的 utility 函数)
│ ├── view (用于放置模板文件)
│ | └── home.tpl
├── |── model (用于放置领域模型)
│ | └── home.tpl
│ └── extend (用于框架的扩展)
│ ├── helper.js (可选)
│ ├── request.js (可选)
│ ├── response.js (可选)
│ ├── context.js (可选)
│ ├── application.js (可选)
│ └── agent.js (可选)
├── config(用于编写配置文件)
| ├── plugin.js(用于配置需要加载的插件)
| ├── config.default.js
│ ├── config.prod.js
| ├── config.test.js (可选)
| ├── config.local.js (可选)
| └── config.unittest.js (可选)
└── test(用于单元测试)
├── middleware
| └── response_time.test.js
└── controller
└── home.test.js
访问
文件 app ctx service config logger helper
Controller this.app this.ctx this.service this.config this.logger this.app.helper
Service this.app this.ctx this.service this.config this.logger this.app.helper
初始化项目
mkdir egg-news
cd egg-news
npm init -y
cnpm i egg --save
cnpm i egg-bin --save-dev
-
添加 npm scripts 到 package.json:
“scripts”: {
“dev”: “egg-bin dev”
} -
跑通路由
├─app
│ │─router.js
│ ├─controller
│ │ news.js
├─config
│ config.default.js
|─package.json -
配置路由
// app/router.jsmodule.exports = app => { const { router, controller } = app; router.get('/news', controller.news.index); }
-
编写控制器
//- app\controller\news.jsconst { Controller } = require('egg'); class NewsController extends Controller { async index() { this.ctx.body = 'hello world'; } } module.exports = NewsController;
-
编写配置文件
exports.keys = ‘zfpx’;
静态文件中间件
-
Egg 内置了 static 插件
static 插件默认映射 /public/ -> app/public/ 目录
把静态资源都放到 app/public 目录即可
bootcss -
使用模板引擎
├─app
│ │─router.js
│ ├─controller
│ │ news.js
│ ├─public
│ │ ├─css
│ │ │ bootstrap.css
│ │ └─js
│ │ bootstrap.js
│ └─view
│ news.ejs
├─config
│ config.default.js
│ plugin.js -
安装依赖的插件
cnpm install egg-view-nunjucks --save -
启用插件
//- {ROOT}\config\plugin.jsexports.nunjucks = { enable: true, package: 'egg-view-nunjucks' }
-
配置模板
// - {ROOT}\config\config.default.js
module.exports=app => {
let config={};config.keys=‘zfpx’;
config.view={
defaultExtension: ‘.html’,
defaultViewEngine: ‘nunjucks’,
mapping: {
‘.html’:‘nunjucks’
}
}
return config;
}
-
编写模板
{{title}} {% for news in list%} {% endfor %}
读取远程接口服务
在实际应用中,Controller 一般不会自己产出数据,也不会包含复杂的逻辑,复杂的过程应抽象为业务逻辑层 Service。
-
添加配置
// - config.default.jsconfig.news={ newsListUrl: 'https://www.easy-mock.com/mock/5b923eb2321f1076a4fc13f4/api/news', }
-
编写Service
// - const {Service}=require(‘egg’);
class NewsService extends Service {
async list(pageNum,pageSize) {
const {ctx}=this;
const {newsListUrl}=this.config.news;
const result=await ctx.curl(newsListUrl,{
method: ‘GET’,
data: {
pageNum,pageSize
},
dataType:‘json’
});
return result.data.data;
}
}
module.exports=NewsService; -
编写控制层
app/controller/news.jsconst {Controller}=require('egg'); class NewsController extends Controller{ async index() { const {ctx,service}=this; let {pageNum=1,pageSize=this.config.news.pageSize}=ctx.query; const list=await service.news.list(pageNum,pageSize); await ctx.render('index',{list}); } } module.exports=NewsController;
扩展工具方法
- egg最重要的5个对象
- app 代表整个应用对象
- ctx 代表上下文对象
- request 代表请求对象
- response 对象
- helper 工具方法
- 框架提供了一种快速扩展的方式,只需在app/extend目录下提供扩展脚本即可
- Helper 函数用来提供一些实用的 utility 函数。
- 访问方式 通过 ctx.helper 访问到 helper 对象
app\extend\helper.js
const moment=require('moment');
moment.locale('zh-cn');
exports.fromNow=dateTime => moment(new Date(dateTime)).fromNow();
news.js
list.forEach(item => {
item.createAt=ctx.helper.fromNow(item.createAt);
return item;
});
index.html
时间: {{helper.fromNow(news.createAt)}}
中间件
app/middleware/robot.js
module.exports=(options,app) => {
return async function(ctx,next) {
const source=ctx.get('user-agent')||'';
const matched=options.ua.some(ua => ua.test(source));
if (matched) {
ctx.status=403;
ctx.body='你没有访问权限';
} else {
await next();
}
}
}
config.default.js
config.middleware=[
'robot'
]
config.robot={
ua: [
/Chrome/
]
}
运行环境
框架有两种方式指定运行环境:
-
通过 config/env 文件指定,该文件的内容就是运行环境,如 prod。
-
通过 EGG_SERVER_ENV 环境变量指定。
-
框架提供了变量 app.config.env 来表示应用当前的运行环境。
-
支持按环境变量加载不同的配置文件,如 config.local.js, config.prod.js 等等
EGG_SERVER_ENV 说明
local 本地开发环境
prod 生产环境npm install cross-env --save-dev
“scripts”: {
“start”: “cross-env EGG_SERVER_ENV=local egg-bin dev”,
“debug”: “egg-bin debug”
}
单元测试