Eggjs是什么?
Eggjs是一个基于Koajs的框架,所以它应当属于框架之上的框架,它继承了Koajs的高性能优点,同时又加入了一些约束与开发规范,来规避Koajs框架本身的开发自由度太高的问题。
Koajs是一个nodejs中比较基层的框架,它本身没有太多约束与规范,自由度非常高,每一个开发者实现自己的服务的时候,都有自己的“骚操作”。而egg为了适应企业开发,加了一些开发时的规范与约束,从而解决Koajs这种自由度过高而导致不适合企业内使用的缺点,Egg便在这种背景下诞生。
Egg是由阿里巴巴团队开源出来的一个“蛋”,为什么是个蛋?蛋是有无限可能的,鸡孵出的蛋生小鸡,恐龙孵出来的蛋就是恐龙,这也正更好的体现了egg最大的一个亮点“插件机制”,每个公司每个团队甚至单个开发者都可以在这之上孵化出最适合自己的框架。像阿里内部不同的部门之间都孵化出了合适自己的egg框架,如蚂蚁的chair,UC的Nut,阿里云的aliyun-egg等。
现有的Nodejs框架与Eggjs对比
Express和Egg的对比
Express和Koa两个框架是同一班人发布的,首先Koa肯定先天就有express不能替代的优势,那也代表着以Koa为基础的egg本身比express也是有优势的。在Express这个框架在使用的时候,由于框架的自由度很高,每个开发者都化身为哈姆雷特。比如实现某一个功能的时候,第一个使用者喜欢把controller和service区分开,另一个使用者却就喜欢写在一起,这样的结果就是同是express的项目,换一个人来维护时,成本变得很高,因为你不知道前面开发者的骚操作到底能骚到什么地步。而egg为了企业中使用相同的规范去开发,本身奉行“约定大于配置”的原则,就如上面这个例子,它本身就约定了这个功能该有怎样的规范去实现,从而使得它能在企业框架域中站住脚,发挥Koajs的价值。
Sails和Egg的对比
Sails框架也是一个nodejs为基础的企业级框架,笔者在之前一份工作中,后端正是使用这个框架,正好也对比一下这两个框架。sails的思想是ruby语言的框架rails借鉴来的,它是以express为基础的一个MVC框架,本身也是奉行“约定大于配置”的原则来面向开发者,但是它本身并不属于精巧的那种,框架自身内置了一些常用的功能,例如它的 blueprints,自动生成restApi路由的功能,但是其实我们在正式开发的时候因为这个功能的不能满足我们的要求,实际是不开启这个功能的。它本身还集成了前端模块进去,但是我们只将其作为后端服务来用,也从来没有使用过这些功能。而egg则非常的小巧,所有的模块功能均以插件的模式由开发者选择是否需要被安装使用,完全可以按照自己的需求去觉得框架那些需要安装,做的定制开发。
eggjs项目规范介绍
安装egg
npm init egg --type=simple
npm i // 安装依赖
框架约定的目录介绍
- 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机制。
一个基础的 API 大致由路由、获取请求参数、逻辑处理、返回响应数据几部分组成
路由
app/router.js 用于配置 URL 路由规则
router.get("/", controller.home.index);
// 当访问GET '/' ,app/controller/home.js 下的 index 方法会执行
router.post("/create", controller.user.create);
// 当访问POST '/create' ,app/controller/user.js 下的 create 方法会执行
获取请求参数
this.ctx.query获取 URL 中 ? 后面的部分参数
// GET /posts?category=egg&language=node
// app/controller/post.js
class PostController extends Controller {async listPosts() {const query = this.ctx.query;// {// category: 'egg',// language: 'node',// }}
}
this.ctx.params获取路由中的动态参数
// app.get('/projects/:projectId/app/:appId', controller.app.listApp);
// GET /projects/1/app/2
class AppController extends Controller {async listApp() {const params = this.ctx.params;// {// projectId: '1',// appId: '2'// }}
}
this.ctx.request.body获取 body 参数
// POST /api/posts HTTP/1.1
// Host: localhost:3000
// Content-Type: application/json; charset=UTF-8
//
// {"title": "controller", "content": "what is controller"}
class PostController extends Controller {async listPosts() {const body = this.ctx.request.body;// {// title: 'controller',// content: 'what is controller'// }}
}
返回响应数据
this.ctx.body返回响应数据
class ViewController extends Controller {async show() {// 返回Content-Type为application/json的bodythis.ctx.body = {name: "egg",category: "framework",language: "Node.js",};}async page() {// 返回Content-Type为text/html的bodythis.ctx.body = "<html><h1>Hello</h1></html>";}
}