egg.js是阿里推出的基于koa的node开发框架,今天抽空体验了下,按官方教程做一个Hacker News。其实官方有脚手架提供,但是这次我们不用。
开始之前,我们先看下KOA对于中间件的洋葱模型,了解这个,对于我们之后理解一个请求的执行路径会很有帮助。
好了,让我们开始我们的egg之旅吧!
1, 先初始化项目结构:
$ mkdir egg-example
$ cd egg-example
$ npm init
$ npm i egg --save
$ npm i egg-bin --save-dev
2, 在package.json里,添加如下命令:
"scripts": {
"dev": "egg-bin dev"
}
3, 开始编写代码,这之前,我们应该对项目的目录结构有个约定,官方的说明在这里 https://eggjs.org/zh-cn/basic... 我们到时候在回来说下这个目录。
4 我们需要一个controller,一个router,一个config,内如如下
// app/controller/home.js
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
this.ctx.body = 'Hello world';
}
}
module.exports = HomeController;
// app/router.js
module.exports = app => {
const { router, controller } = app;
router.get('/', controller.home.index);
};
// config/config.default.js
exports.keys = <此处改为你自己的 Cookie 安全字符串>;
此时,目录结构如下:
egg-example
├── app
│ ├── controller
│ │ └── home.js
│ └── router.js
├── config
│ └── config.default.js
└── package.json
好了,现在检查下,运行 npm run dev,
在 http://127.0.0.1:7001/ 检查下,一切ok
这里有几个地方要注意下
-
Controller 有class和exports两个写法,那么这两个写法有什么区别呢?
按照类的方式编写Controller,不仅可以让我们更好的对 Controller层代码进行抽象(例如将一些统一的处理抽象成一些私有方法),还可以通过自定义Controller 基类的方式封装应用中常用的方法。至于方法的方式,官方不推荐使用,只是为了做兼容,其中,每一个 Controller 都是一个 async function,它的入参为请求的上下文 Context 对象的实例,通过它我们可以拿到框架封装好的各种便捷属性和方法
-
config也有module.exports 和 exports两种写法,那么这两种写法有什么区别呢?
module.exports是Module系统创建对象的语法,但是如果你希望你的 module是一个类的实例,你可以将实例赋予moduel.exports,如这时候 module.exprots指向的就是一个A的实例了,可以用以下方式调用A的方 法 module.exports.xxx(),等价于 a.xxx()。但是如果只是exports= new ClassA();这个只是简单的将本模块变量exports重新绑定了而已。注 意,对module.exports的绑定不能是异步绑定或者回调中! 可以这样理解,其他模块使用本模块时,用的是module.exports指向的东 西,而exports是模块内部变量,外部模块是无法访问的。 module.exports和exports是两个变量,只是一开始这两个是指向同一个对 象而已。可以在模块内部用exports作为module.exports的快捷方式
现在,我们看下官方的目录结构规范:
egg-project
├── package.json
├── app.js (可选)
├── agent.js (可选)
├── app
| ├── router.js
│ ├── controller
│ | └── home.js
│ ├── service (可选)
│ | └── user.js
│ ├── middleware (可选)
│ | └── response_time.js
│ ├── schedule (可选)
│ | └── my_task.js
│ ├── public (可选)
│ | └── reset.css
│ ├── view (可选)
│ | └── 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/router.js 用于配置 URL 路由规则,具体参见 Router。
app/controller/** 用于解析用户的输入,处理后返回相应的结果,具体参见 Controller。
app/service/** 用于编写业务逻辑层,可选,建议使用,具体参见 Service。
app/middleware/** 用于编写中间件,可选,具体参见 Middleware。
app/public/** 用于放置静态资源,可选,具体参见内置插件 egg-static。
app/extend/** 用于框架的扩展,可选,具体参见框架扩展。
config/config.{env}.js 用于编写配置文件,具体参见配置。
config/plugin.js 用于配置需要加载的插件,具体参见插件。
test/** 用于单元测试,具体参见单元测试。
app.js 和 agent.js 用于自定义启动时的初始化工作,可选,具体参见启动自定义。关于agent.js的作用参见Agent机制。
由内置插件约定的目录:
app/public/** 用于放置静态资源,可选,具体参见内置插件 egg-static。
app/schedule/** 用于定时任务,可选,具体参见定时任务。
若需自定义自己的目录规范,参见 Loader API
app/view/** 用于放置模板文件,可选,由模板插件约定,具体参见模板渲染。
app/model/** 用于放置领域模型,可选,由领域类相关插件约定,如 egg-sequelize。
(未完待续)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。