egg.js是阿里推出的基于koa的node开发框架,今天抽空体验了下,按官方教程作一个Hacker News。其实官方有脚手架提供,可是此次咱们不用。css
开始以前,咱们先看下KOA对于中间件的洋葱模型,了解这个,对于咱们以后理解一个请求的执行路径会颇有帮助。
好了,让咱们开始咱们的egg之旅吧!html
1, 先初始化项目结构:node
$ mkdir egg-example $ cd egg-example $ npm init $ npm i egg --save $ npm i egg-bin --save-dev
2, 在package.json里,添加以下命令:npm
"scripts": { "dev": "egg-bin dev" }
3, 开始编写代码,这以前,咱们应该对项目的目录结构有个约定,官方的说明在这里 https://eggjs.org/zh-cn/basic... 咱们到时候在回来讲下这个目录。json
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 安全字符串>;
此时,目录结构以下:app
egg-example ├── app │ ├── controller │ │ └── home.js │ └── router.js ├── config │ └── config.default.js └── package.json
好了,如今检查下,运行 npm run dev,
在 http://127.0.0.1:7001/ 检查下,一切ok框架
这里有几个地方要注意下koa
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。
(未完待续)