Nodejs框架演進之路

Nodejs框架演進之路

大部分框架的演進之路大致都是同樣的javascript

  • 實現(土方法)
  • 實踐(項目實操)
  • 看齊最佳實踐
  • 不斷封裝、造輪子
  • 走出本身的特點

下面簡單的介紹一下moajs的演進之路php

什麼是Moajs?

moajs是我司開發的開源nodejs web框架。css

https://github.com/moajs前端

目前主要java

  • moa-api
  • moa-frontend
  • moa-h5
  • mongoosedao
  • res.api
  • mount-routes

moa是做爲名詞是恐鳥(一種新西蘭無翼大鳥,現已滅絕) https://en.wikipedia.org/wiki/Moanode

階段0:原始的Expressjs

最開始的時候都是使用express-generator生成的項目骨架nginx

➜  test  express express-test

   create : express-test
   create : express-test/package.json
   create : express-test/app.js
   create : express-test/public
   create : express-test/public/javascripts
   create : express-test/views
   create : express-test/views/index.jade
   create : express-test/views/layout.jade
   create : express-test/views/error.jade
   create : express-test/public/stylesheets
   create : express-test/public/stylesheets/style.css
   create : express-test/routes
   create : express-test/routes/index.js
   create : express-test/routes/users.js
   create : express-test/public/images
   create : express-test/bin
   create : express-test/bin/www

   install dependencies:
     $ cd express-test && npm install

   run the app:
     $ DEBUG=express-test:* npm start

➜  test  cd express-test 
➜  express-test  tree . -L 1 -d
.
├── bin
├── public
├── routes
└── views

4 directories

express是遵循小而美的原則,因此只有routes和views層,不足以在項目裏使用的。git

階段1:抽象config和controller、model、middleware等

$ tree . -L 1 -d
.
├── actions
├── config
├── cron_later
├── doc
├── middleware
├── migrate
├── models
├── node_modules
├── public
├── queues
├── routes
├── test
├── tmp
├── uploads
└── views

說明es6

  • 繼承express-generator的結構(routes和views)
  • actions即controller控制器層
  • models即模型層
  • config是配置項目錄
  • middleware中間件層
  • migrate是咱們處理數據的,跟rails的migrate不徹底同樣
  • test是測試目錄
  • queues是隊列
  • cron_later是調度
  • doc文檔
  • uploads是上傳自動建立的目錄

這階段僅僅是用,算是基於express抽象了一點業務、配置相關的東西而已,目錄多了依然蛋疼github

階段2:向rails看齊

目錄結構

➜  moa-api git:(master) ✗ tree . -L 2 -d
.
├── app
│   ├── controllers
│   ├── middlewares
│   ├── models
│   ├── routes
│   ├── services
│   └── views
├── bin
├── config
├── doc
├── logs
├── migrate
├── public
└── test
    └── controller

42 directories

說明

  • 使用app做爲代碼管理目錄,歸類可變代碼都放到app下面
  • 其餘沿用【階段1】的設計

具體看一下app目錄下的分類

├── app
│   ├── controllers
│   ├── middlewares
│   ├── models
│   ├── routes
│   ├── services
│   └── views

說明

  • mvc和rails的都同樣
  • middlewares是express的概念,放這裏比較合適,若是像rails同樣設置plugin也能夠考慮,不如放到此處更容易理解
  • services層實際是java裏面喜歡用的概念,多個模型dao的操做,當作是一個業務,因此複雜業務場景下,services層有它的好處

你看不到的優化

  • 使用mongoosedao把mongoose的crud、分頁等封裝了dao操做
  • 使用mount-routes自動掛載路由,讓你只關係路由內容,而沒必要關係url地址,這樣也算coc的一種(約定大於配置)
  • 使用res.api約定api返回數據

至此,moajs的0.x版本,特性已經足夠了。

其實moajs還提供腳手架scaffold和插件機制

腳手架scaffold

moag order product_name:string product_count:string all_price:string status:string delivery_num:string pay_num:string activity_id:string  owner_id:string contact_id:string

生成目錄以下

➜  moa-scaffold  tree .
.
└── app
    ├── controllers
    │   └── orders_controller.js
    ├── models
    │   └── order.js
    ├── routes
    │   ├── api
    │   │   └── orders.js
    │   └── orders.js
    └── views
        └── orders
            ├── edit.jade
            ├── index.jade
            ├── new.jade
            ├── order.jade
            └── show.jade

7 directories, 9 files

這個生成器的原理是咱們參考rails的腳手架,代碼結構,mvc都很是方便

須要說明的是

  • 先有結構
  • 而後纔有腳手架

插件機制

你們都知道express基於connect,有middleware中間件的概念,它自己遵循小而美的設計哲學,致使它很是精簡

從express@generator來看,它就只能作點小打小鬧的東西,若是要設計一個複雜的大系統,就免不了和代碼結構,模塊,組件等戰鬥

從個人角度講,這些東西均可以理解成是業務插件,好比對於一個框架來講,用戶管理就應該像ruby裏的devise同樣,以一個gem的形式存在,若是代碼裏引用,調用就行了。

gem + rails plugin機制能夠作,那麼express + npm也是能夠的,可是咱們缺乏的plugin機制,先說利用npm的回調實現它的可能性

好比在一個boilerplate項目裏,咱們安裝插件

npm install --save moa-plugin-user

安裝完成以後,咱們須要對項目裏的文件或配置也好作一個插件登記,這些東西是否能夠放到postinstall裏呢?

剩下的就都是nodejs代碼了,你們寫就行了。

moajs裏0.x版本使用軟鏈接建立插件

  • nmm用於插件管理和初始化
  • 使用npm的postinstall hook完成安裝工做
  • 使用軟鏈接的方式建立插件(簡單粗暴法)

這其實有不少痛苦,每次升級插件都須要在主庫裏更新,之後仍是要放到目錄裏,按照php的作法走。

總結

總結一下moajs的特性

  • 配置化
  • 目錄和rails相似
  • 腳手架scaffold
  • 插件機制
  • 一些咱們總結的最佳實踐

具體

  • 自動加載路由
  • 支持mongodb配置
  • 集成mongoosedao,快速寫crud等dao接口
  • 自帶用戶管理
  • 使用jsonwebtoken作用戶鑑權
  • 支持migrate測試
  • 支持mocha測試
  • 默認集成res.api,便於寫接口
  • 集成supervisor,代碼變更,自動重載
  • gulp自動監控文件變更,跑測試
  • gulp routes生成路由說明
  • 使用log4js記錄日誌
  • 集成kue隊列[須要使用mount-queues插件]

階段3:走本身的路

上一個階段【階段2:向rails看齊】其實仍是基於express的最佳實踐而已。代碼裏到處都是express的影子,因此moajs 0.x版本真的只是基於express的最佳實踐。

可是技術的演進步伐很是快

  • es6和7來了
  • async/generator也來了
  • koa來了
  • typescript來了
  • ...

這些對咱們來講都是要思考的

先後端分離

  • 前端:moa-frontendmoa-h5
    • public下面的採用nginx作反向代理
    • 其餘的採用express+jade精簡代碼(ajax與後端交互)
  • 後端:moa-api

微內核base2

以前使用express,各類配置都在app.js裏,噁心的要死,並且沒有app的生命週期管控

因而寫了base2,它是一個高度可配置的帶有應用生命週期管控的 nodejs web 微框架(同時支持express和koa)

https://github.com/base-n/base2-core

Usages

var app = require('base2')({
  // debug: true,
  root:__dirname,
  "views": "views",
  "routes": "routes2",
  "public": "public",
})

app.start(3019);
  • 若是有views目錄就能夠顯示視圖
  • 若是有routes目錄,就能夠自動掛載路由
  • 若是有public就有靜態server,目錄隨便指就行了

簡單吧,下面講講爲啥這樣設計。

咱們對項目的認知

  • framework(框架選項)
    • express
    • koa
  • env(環境,參考rails的環境說明)
    • production
    • development
    • test
  • type(類型,咱們對項目分類,有的是帶視圖的,有的是api的,有的rpc服務的,all即全部)
    • normal
    • api
    • all
    • service

這些其實對express和koa的中間件分類的維度。也就是說不一樣場景,咱們加載不通的中間價。

那麼咱們何時加載呢?你想可配置,可高度配置,你就必定得留出足夠的點,讓以前能夠完成功能也能很好的集成進來。

因而引出app的生命週期,咱們能夠反思一下app.js裏都作了什麼?

  • 設置
  • 全局中間件
  • 路由

其餘都指出去了。

那麼咱們就能夠抽象一下了

  • config.pre
  • settings
    • config.before_settings
    • config.after_settings
  • global_middlewares
    • config.before_global_middlewares
    • config.after_global_middlewares
  • routes
    • config.before_routes
    • config.after_routes
  • config.post

實際上也是以前app作的事兒,可是要放到配置項裏,按需採用。

舉個例子,moa-api裏的app.js 改寫後

require('./init')
require('./db')

var log4js        = require('log4js'); 
var res_api       = require('res.api');
var log           = log4js.getLogger("moa-api");

var app = require('base2')({
  // debug: true,
  root:__dirname,
  "pre": function(app) {
    app.use(res_api);
  },
  "views": "app/views",
  "routes": "app/routes",
  "public": "public"
})

res_api是一箇中間件,若是想在路由裏直接使用res.api方法,就必須先掛載。

這裏選了pre這個最先執行的生命週期方法。其實也能夠routes前面的全部生命週期均可以。

兼容koa和express

噱頭而已,其實兼容與否並不重要,base2給咱們提供了這種可能,咱們用就行了

經過koa-generator你們能夠體驗一下koa1和koa2的寫法和express的差異。

另外我組織了你們《一塊兒學koa》

http://base-n.github.io/koa-generator-examples

歡迎參與

Next

moajs在設計、實踐上都是不錯的,不過目前還不夠完善,但願你們能夠多多參與

下一步還在作

將來路還很遠。。。但很美好

全文完

歡迎關注個人公衆號【node全棧】

node全棧.png

相關文章
相關標籤/搜索