koa-grace:一個基於koa的node多應用MVC框架

春節期間沒回家留在北京寫了一個基於koa的node MVC框架:koa-grace ,你們有興趣能夠star & fork下,謝謝支持啦!!javascript

img

項目地址:html

https://github.com/xiongwilee/koa-gracejava

詳細文檔:node

1. 簡介

koa-grace是基於koa 1.x的Nodejs多站點MVC框架。react

1.1 特徵

爲何koa-grace是新一代Nodejs MVC框架:git

  • 一個node服務,多個站點應用;github

  • yield 異步語法支持,忘掉回調噩夢;mongodb

  • 繼承koa中間件,擴展性更強;數據庫

  • 支持路徑即路由,更優雅的路由方式;npm

  • RESTful數據代理支持,先後端徹底解耦;
    ……

1.2 目錄結構

├── app                        // 站點總目錄
│   ├── blog                     // 站點:blog目錄
│   │   ├── controller                 // 站點:blog的路由(控制器)目錄
│   │   ├── model                     // 站點:blog的模型目錄,包括公共控制器、mongo等
│   │   ├── static                     // 站點:blog的靜態文件目錄
│   │   └── views                     // 站點:blog的html模板目錄
│   ├── reactjs-boilerplate     // 站點:reactjs-boilerplate目錄
│   └── shop                     // 站點:shop目錄
├── bin                        // server啓動器目錄
│   ├── koa-grace                 // TODO:命令行工具
│   └── server.js                  // server啓動器
├── config                     // 配置文件目錄
│   └── main.js                    // 主配置文件
├── package.json
└── src                        // 核心文件
    └── app.js                    // 主文件

2. 快速開始

在開始使用koa-grace以前請確保您已經安裝並運行了下面的工具:

  • Nodejs (v4+)

  • MongoDB (DEMO 演示使用,正式環境能夠配置不用)

2.1 安裝

$ git clone https://github.com/xiongwilee/koa-grace.git 
$ cd koa-grace && npm install

2.2 配置

在koa-grace目錄下,打開配置文件:

$ vi config/main.js

修改配置項:config.mongo.blog 爲您的本地mongoDB的路徑:

// mongo configuration
mongo: {
  'blog': 'mongodb://localhost:27017/blog'
}

**更多關於配置項的文檔能夠看下面的使用文檔。

2.3 運行

在koa-grace目錄下執行,可能須要root權限:

$ npm run dev

而後訪問 http://127.0.0.1:3000 ,就能夠看到koa-grace其中的一個案例站點了!

您也能夠訪問koa-grace的一個線上應用: http://mlsfe.biz

3. 詳細使用文檔

雖然說koa-grace是一個完整的MVC框架 , 但其本質是基於一種多站點解決方案的koa中間件的集合。其核心中間件包括但不只限於: koa-router , koa-views , koa-mount , koa-static , koa-grace-vhost , koa-grace-router , koa-grace-proxy , koa-grace-model , koa-grace-mongo , ...

3.1 多站點配置 - Vhost

koa-grace是基於 koa-grace-vhost 進行vhost管理,基本原理是:

一個域名對應一個應用,一個應用對應一個目錄

如此一來,配置多站點就很簡單了,在配置文件config/main.js中:

// vhost配置
vhost: {
  'test.mlsfe.biz':'blog',
  '127.0.0.1':'blog',
  'localhost':'shop',
  '0.0.0.0':'reactjs-boilerplate'
}

其中,vhost配置中127.0.0.1是URI的hostname, blog是站點總目錄app下的一個目錄app/blog。若是當前請求URI爲:http://127.0.0.1/home 則koa-grace會自動訪問app/blog目錄裏的路由、模型、靜態文件。

須要說明的是,多站點配置僅以URI的hostname爲主鍵 ;也就是說,訪問帶端口號的http://127.0.0.1:3000/home 也會定位到app/blog目錄。

3.2 路由及控制器 - Router&Controller

很好,若是你配置好了一個vhost爲'127.0.0.1':'blog' , koa-grace就會自動生成一個vhost到app/blog目錄了!接下來,進入app/blog/controller目錄進行路由配置。

koa-grace基於 koa-grace-router 進行路由管理的,koa-grace-router又是依賴於:koa-router

3.2.1 文件路徑即路由

blog站點爲例,koa-grace-router會找到 app/blog/* 目錄下的全部.js後綴的文件,並以文件路徑生成路由。咱們再看一下案例中blog的路由文件:

├── api
│   └── post.js
├── dashboard
│   ├── post.js
│   ├── site.js
│   ├── user.js
│   └── userAuthor.js
├── error.js
├── home.js
├── post.js
└── user.js

若是當前請求URI爲:http://127.0.0.1/dashboard/post/* 則路由將自動落在dashboard/post.js文件中。

那麼,若是請求路徑若是是http://127.0.0.1/dashboard/post/list ,這個dashboard/post.js文件是如何控制的呢?

3.2.2 路由文件詳細說明

打開app/blog/controller/dashboard/post.js文件:

/*...*/
exports.list = function* () {
  // 綁定默認控制器
  yield this.bindDefault();
  // 獨立權限控制
  if (!userAuthor.checkAuth(this, this.userInfo)) {return};
  
  // 獲取請求query參數
  let pageNum = this.query.page;
  // 獲取數據
  let PostModel = this.mongo('Post');
  let posts = yield PostModel.page(pageNum,20);
  let page = yield PostModel.count(pageNum,20);

  // 渲染模板
  yield this.render('dashboard/post_list',{
    breads : ['文章管理','文章列表'],
    posts:posts,
    page:page,
    userInfo: this.userInfo,
    siteInfo: this.siteInfo
  })
}
exports.list.__method__ = 'get';
exports.list.__regular__ = null;
/*...*/

對,就是你猜的那樣:koa-grace-router是經過post.js的module.exports進行下一步的路由控制。

另外,須要說明如下幾點:

  • 若是須要配置dashboard/post/list請求爲POST方法,則post.js中聲明 exports.list.__method__ = 'post'便可(不聲明默認爲get請求),更多方法類型請參看:koa-router#routergetputpostpatchdelete--router;

  • 若是要進一步配置dashboard/post/list/id路由,則在post.js中聲明exports.list.__regular__ = '/:id';便可,更多相關配置請參看:koa-router#named-routes

  • 若是當前文件路由就是一個獨立的控制器,則module.exports返回一個yield方法便可,能夠參考案例blog中的controll/home.js

  • 若是當前文件僅僅是一個依賴,僅僅被其餘文件引用;則在文件中配置exports.__controller__ = false,該文件就不會生成路由了

固然,若是一個路由文件中的控制器方法都是post方法,您能夠在控制器文件最底部加入:module.exports.__method__ = 'post'便可。__regular__的配置同理。

3.2.3 控制器

剛剛咱們看到了post.js中的exports.list方法,事實上它就是一個控制器(controller)了。

您能夠新建一個app/blog/controller/hello.js文件

exports.koagrace = funtion* (){
    this.body = 'hello koa-grace!';
}

訪問 http://127.0.0.1/hello/koagrace ,就能夠看到「hello koa-grace!」輸出。它是典型的一個基於上下文(context)的yield方法。幾個關鍵方法/參數使用以下:

context屬性 類型 說明
this.query object get參數
this.request.body object post參數,因爲koa-grace默認引入了koa-bodypaser,您能夠直接在this.request.body中獲取到post參數
this.bindDefault function 公共控制器,至關於require('app/blog/model/defaultCtrl.js')
this.render function 模板引擎渲染方法,請參看:3.5 模板引擎- Template engine
this.mongo function 數據庫操做方法,請參看:3.3 數據庫 - Database
this.mongoMap function 並行數據庫多操做方法,請參看:3.3 數據庫 - Database
this.proxy function RESTful數據請求方法,請參看:3.4.1 數據代理
this.download function 文件請求代理方法,請參看:3.4.2 請求代理
this.upload function 文件上傳方法,請參看: 3.4.3 文件上傳

更多context文檔請參看koa官網,或http://koajs.in/doc/

3.3 數據庫 - Database

koa-grace引入基於mongoosekoa-grace-mongo ,能夠很是便捷地使用mongoDB。

3.3.1 鏈接數據庫

在配置文件config/main.js中進行配置:

// mongo配置
  mongo: {
    options:{
      // mongoose 配置
    },
    api:{
      'blog': 'mongodb://localhost:27017/blog'
    }
  },

其中,mongo.options配置mongo鏈接池等信息,mongo.api配置站點對應的數據庫鏈接路徑。

值得注意的是,配置好數據庫以後,一旦koa-grace server啓動mongoose就啓動鏈接,直到koa-grace server關閉

3.3.2 mongoose的schema配置

依舊以案例blog爲例,參看app/blog/model/mongo目錄:

└── mongo
    ├── Category.js
    ├── Link.js
    ├── Post.js
    └── User.js

一個js文件即一個數據庫表即相關配置,以app/blog/model/mongo/Category.js

'use strict';

// model名稱,即表名
let model = 'Category';

// 表結構
let schema = [{
  id: {type: String,unique: true,required: true},
  name: {type: String,required: true},
  numb: {type: Number,'default':0}
}, {
  autoIndex: true,
  versionKey: false
}];

// 靜態方法:http://mongoosejs.com/docs/guide.html#statics
let statics = {}

// 方法擴展 http://mongoosejs.com/docs/guide.html#methods
let methods = {
  /**
   * 獲取博客分類列表
   */
  list: function* () {
    return this.model('Category').find();
  }
}

module.exports.model = model;
module.exports.schema = schema;
module.exports.statics = statics;
module.exports.methods = methods;

主要有四個參數:

  • model , 即表名,最好與當前文件同名

  • schema , 即mongoose schema

  • methods , 即schema擴展方法,推薦把數據庫元操做都定義在這個對象中

  • statics , 即靜態操做方法

3.3.3 在控制器中調用數據庫

在控制器中使用很是簡單,主要經過this.mongo,this.mongoMap兩個方法。

1) this.mongo(name)

調用mongoose Entity對象進行數據庫CURD操做

參數說明:

@param [string] name : 在app/blog/model/mongo中配置Schema名,

返回:

@return [object] 一個實例化Schema以後的Mongoose Entity對象,能夠經過調用該對象的methods進行數據庫操做

案例

參考上文中的Category.js的配置,以app/blog/controller/dashboard/post.js爲例,若是要在博客列表頁中獲取博客分類數據:

// http://127.0.0.1/dashboard/post/list
exports.list = function* (){
    let cates = yield this.mongo('Category').list();
    this.body = cates;
}

2)this.mongoMap(option)

並行多個數據庫操做

參數說明

@param [array] option
@param [Object] option[].model mongoose Entity對象,經過this.mongo(model)獲取
@param [function] option[].fun mongoose Entity對象方法
@param [array] option[].arg mongoose Entity對象方法參數

返回

@return [array] 數據庫操做結果,以對應數組的形式返回

案例

let PostModel = this.mongo('Post');
  let mongoResult = yield this.mongoMap([{
      model: PostModel,
      fun: PostModel.page,
      arg: [pageNum]
    },{
      model: PostModel,
      fun:PostModel.count,
      arg: [pageNum]
    }]);

  let posts = mongoResult[0];// 獲取第一個查詢PostModel.page的結果
  let page = mongoResult[1]; // 獲取第二個查詢PostModel.count的結果,二者併發執行

3.4 代理 - Proxy

除了在控制器中直接進行數據庫操做,Web應用還有可能由其餘服務進行後端部署。針對這種場景,koa-grace引入了基於 Requestkoa-grace-proxy

3.4.1 數據代理

在koa-grace的控制器中使用this.proxy方法進行數據代理很是簡單:

exports.list = function* (){
    yield this.proxy({
        userInfo:'github:post:user/login/oauth/access_token?client_id=****',
        otherInfo:'github:other/info?test=test',
    });
    
    console.log(this.backData);
    /**
     *    {
     *        userInfo : {...},
     *        otherInfo : {...}
     *    }
     */
}

你也能夠不傳this.backData參數,默認注入到上下文的this.backData對象中:

exports.list = function* (){
    yield this.proxy({
        userInfo:'github:post:user/login/oauth/access_token?client_id=****',
        otherInfo:'github:other/info?test=test',
    });
    
    console.log(this.backData);
    /**
     *    {
     *        userInfo : {...},
     *        otherInfo : {...}
     *    }
     */
}

另外,github:post:user/login/oauth/access_token?client_id=****說明以下:

  • github: 爲在config.main.jsapi 對象中進行配置;

  • post : 爲數據代理請求的請求方法,該參數能夠不傳,默認爲get

  • path: 後面請求路徑中的query參數會覆蓋當前頁面的請求參數(this.query),將query一同傳到請求的接口

  • 你也能夠寫完整的路徑:{userInfo:'https://api.github.com/user/login?test=test'}

3.4.2 文件代理

文件請求代理也很簡單,好比若是須要從github代理一個圖片請求返回到瀏覽器中,參考:http://mlsfe.biz/user/avatar?img=https://avatars.githubusercontent.com/u/1962352?v=3

exports.avatar = function* (){
    let imgUrl = query.img;
    yield this.download(imgUrl);
}

3.4.3 文件上傳

TODO: 文件上傳並代理到其餘服務或者存儲到本地

3.5 模板引擎- Template engine

koa-grace引入koa-views , 進行模板引擎管理。默認的模板引擎爲swig, 您能夠在config/main.js中配置template屬性您想要模板引擎:

// 模板引擎配置
  template: 'swig'

目前支持的模板引擎列表在這裏:consolidate.js#supported-template-engines

在控制器中調用this.render方法渲染模板引擎:

exports.home = function* () {
  yield this.bindDefault();

  yield this.render('dashboard/site_home',{
    breads : ['站點管理','通用'],
    userInfo: this.userInfo,
    siteInfo: this.siteInfo
  })
}

模板文件在app/blog/views目錄中。

3.6 靜態文件服務 - Static server

koa-grace引入koa-mountkoa-static,將靜態文件代理到/static

// 配置靜態文件路由
  vapp.use(mount('/static',
    koastatic(appPath + '/static')
  ));

以案例中blog的靜態文件爲例,靜態文件在blog項目下的路徑爲:app/blog/static/image/bg.jpg,則訪問路徑爲http://127.0.0.1/static/image/bg.jpg

3.7 啓動服務及調試 - Process & DEBUG

3.7.1 開發環境

在開發環境可使用npm命令完成。

1) 普通啓動:

$ npm run start

2) watch啓動:

$ npm run dev
# 在80端口啓動
$ npm PORT=80 run dev
# DEBUG模式啓動,默認爲DEBUG=koa-grace*
$ npm DEBUG=* run dev

3.7.2 生產環境

在生產環境推薦使用 pm2 進行進程管理:

$ npm install pm2 -g
$ pm2 start node ./bin/server.js

更多使用方法,請參看 pm2

5. 貢獻

相關文章
相關標籤/搜索