隨着Nodejs的普及,前端開發的開發場景基本能夠貫穿界面交互到數據存儲,無縫實現全棧開發。最近在實現一個內部項目管理工具的時候,就嘗試了一把接口和數據庫開發。javascript
Egg.js是阿里開源的一套Nodejs開發框架。Egg.js官網的介紹是:前端
Egg.js 爲企業級框架和應用而生,咱們但願由 Egg.js 孕育出更多上層框架,幫助開發團隊和開發人員下降開發和維護成本。java
爲何選擇了Egg.js,而不是Koa,Express呢,其實仍是爲了快速開發,減小搭建項目的時間,Egg.js已經爲開發者設計了幾乎最經常使用的目錄結構,一切傾向於配置化,隱藏一些業務無關的技術細節。開發者能夠更加着重考慮業務邏輯,而後在Egg.js和相關插件的支持下,開發功能便可。mongodb
Egg.js還提倡『約定優於配置』,這一點我也是很贊同,一致的約定可以減小沒必要要的失誤,同時保證了一致的開發體驗,能夠方便的維護不一樣的項目。數據庫
Egg.js提供了腳手架快速初始化項目,可是要求npm >=6.1.0,這基本不是問題。npm
$ mkdir egg-example && cd egg-example
$ npm init egg --type=simple
$ npm i
複製代碼
而後啓動項目api
$ npm run dev
$ open http://localhost:7001
複製代碼
由於Egg.js已經作了太多事情,我只須要關注app和config。跨域
├── app
| ├── router.js
│ ├── controller
│ | └── home.js
│ ├── service
│ | └── user.js
│ ├── model
│ | └── user.js
├── config
| ├── plugin.js
| └── config.default.js
複製代碼
app/router.js 用於配置URL路由規則,也就是你訪問的接口地址,對應的是哪一個controller的邏輯。bash
app/controller/** 用於解析用戶的輸入,處理後返回相應的結果,這裏其實能夠寫service和model的邏輯,可是按照單一職責的原則,咱們會在controller主要放置參數解析和返回值,以及非數據庫操做的邏輯。app
app/service/** 用於編寫業務邏輯層,可選,建議使用,你能夠理解成對數據庫操做的封裝。
app/model/** 用於定義mongodb的schema,這部分很神奇的是Egg.js已經封裝mongodb連接數據庫,並將model綁定到了ctx上,方便調用。
config/config.default.js 用於編寫配置文件,能夠配置不一樣的開發環境,不一樣的變量,可是由於業務比較單一,內部使用,因此只使用了默認設置。個人項目中配置了跨域、mongoose、csrf,等等。
config.mongoose = {
url: "mongodb://127.0.0.1/*****",
options: {}
};
config.cors = {
origin: '*',
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH'
}
config.security = {
csrf: {
enable: false,
},
};
複製代碼
config/plugin.js 用於配置須要加載的插件,好比egg-mongoose,egg-cors。
module.exports = {
mongoose: {
enable: true,
package: "egg-mongoose"
},
cors: {
enable: true,
package: "egg-cors"
}
};
複製代碼
這裏須要注意的是,不少博客提供的代碼都是ES6的代碼,在我初始化的模板中是不可行的,以下:
exports.cors = {
enable: true,
package: 'egg-cors',
}
複製代碼
基礎搭建好了,開發就變得很簡單了,我遵循的邏輯是:Model-->路由-->Contoller-->Service,先設計數據庫Schema,而後增長新的路由,支持對應的Controller,而後在Service中完成數據庫操做。
router.js
router.get("/api/task", controller.task.index);
router.post("/api/task", controller.task.create);
router.put("/api/task/:id", controller.task.update);
router.delete("/api/task/:id", controller.task.destroy );
// 也能夠簡寫爲
router.resources('topics', '/api/task', controller.task);
複製代碼
controller中實現的方法具體能夠參考下面的對應關係
Method | Path | Route Name | Controller.Action |
---|---|---|---|
GET | /posts | posts | app.controllers.posts.index |
GET | /posts/new | new_post | app.controllers.posts.new |
GET | /posts/:id | post | app.controllers.posts.show |
GET | /posts/:id/edit | edit_post | app.controllers.posts.edit |
POST | /posts | posts | app.controllers.posts.create |
PUT | /posts/:id | post | app.controllers.posts.update |
DELETE | /posts/:id | post | app.controllers.posts.destroy |
controller/task.js
exports.index = function*() {
// ...
const result = yield this.service.task.index(this.params);
this.body = result;
};
exports.create = function*() {
// ...
const result = yield this.service.task.create(this.request.body);
this.body = result;
};
exports.update = function*() {
// ...
const result = yield this.service.task.update(this.params.id, this.request.body);
this.body = result;
};
exports.destroy = function*() {
// ...
const result = yield this.service.task.destroy(this.params);
this.body = result;
};
複製代碼
service/task.js
module.exports = app => {
class TaskService extends app.Service {
*index(params) {
let tasks = yield this.ctx.model.Task.find(params);
let result = {};
result.data = tasks;
return result;
}
*create(request) {
}
*update(id, request) {
}
*destroy(params) {
}
}
return TaskService;
};
複製代碼
model/task.js
module.exports = app => {
const mongoose = app.mongoose;
const Schema = mongoose.Schema;
const TaskSchema = new Schema({
id: {type: Number},
text: {type: String},
type: {type: String},
progress: {type: Number},
open: {type: Boolean},
start_date: {type: String},
owner_id: [{type: String}],
duration: {type: Number},
parent: {type: Number}
});
return mongoose.model("Task", TaskSchema);
};
複製代碼
Egg.js 框架內置了 egg-cluster 來啓動 Master 進程,Master 有足夠的穩定性,再也不須要使用 pm2 等進程守護模塊。只須要兩個命令便可:
# 啓動服務
npm start
# 關閉服務
npm run stop
複製代碼
站在巨人的肩膀上,讓咱們的開發效率倍增,可是仍是建議你們先從Koa2學起,對而後對比Egg.js,你就會了解它到底封裝了哪些東西,爲咱們節省了多少工做量,後面還要繼續對Egg.js的插件開發進行了解。