強大的 Node.js Web 框架 - Daze.js

去年年初對 Node.js 比較感興趣,也用了不少 Node.js 的框架,可是開發體驗不是特別好,我以前也是後端轉前端,而後再接觸 Node.js ,因此用過挺多的服務端框架,相對js而言,設計一款服務端框架並不容易,本人也不太願意使用 typescript (爲何不用java,請勿吐槽)編寫而且基於ES6 對入門的小夥伴會更友好一些,而後本身動手開發了一個Node.js 的Web 框架,快過年了纔有時間寫文章(手動狗頭),在這裏給你們分享一下開發經歷。javascript


注:目錄只是爲了好看,想到什麼寫什麼,沒有文筆可言,小白文。前端


選型

對於框架底層,想過本身開發一套(成本過高,而且考慮到生態問題)被我否決了,而後比較了 Koa2 與 Express 最終選擇Koa2做爲默認底層(最後因爲框架的架構設計,koa2服務或者express均可以做爲底層庫🤣),不過最後仍是選擇了 koa2 默認集成。java

既然選擇了 koa2 那天然也是兼容 koa2 的生態圈git


架構設計

剛開始開發的時候實際上是順着koa的路子走的, 以koa做爲底層,對koa的ctx進行擴展,後來以爲這樣子封裝一個koa的全家桶貌似沒什麼意義(晚上一大堆,造輪子沒什麼意義,和別的框架有啥區別,請原諒我這老土的想法🤪),而後開始思考🤔:作這個框架的初衷和意義。github

做爲一個後端過來的,天然就想到了用IOC容器做爲底層更優雅,可是js並無類型約束,接口等特性,也看過不少 typescript的實現(和其餘後端框架並沒有明顯區別,不是我吐槽,其餘語言的更完善更安全性能更好),我下定決心要寫一個js(ES6)版的出來(學習成本低,更好入門🤭就是這麼自覺得是),而後就這樣開啓了個人 Node.js 之旅。web

寫偏了。。下面介紹一下這個框架的架構:typescript

以容器做爲底層,應用類集成容器基類並綁定在容器中,是應用程序對象也是容器的保姆。express

其餘全部的服務(包括 koa 、router、logger、validate、request、response等等)都是以提供者的形式在應用程序中註冊(實際綁定到了容器)。npm

容器開發

前期沒想那麼多,開發容器也很順利,在設計依賴注入模式的時候(因爲沒有接口),想躲過不少方案,最後決定使用裝飾器(真香),不是ts,使用ECMA草案中裝飾器(使用 babel轉碼),最後1.0定稿之後,會成爲可選方案,裝飾器能夠增長開發體驗,但不是必須的,而且強烈推薦的模式進行設計。後端

例如咱們開放一個端點(路由),裝飾器例子,不是注入:

@Router('users')
class UserController {
    @Get()
    index() {
        // ...
    }
}複製代碼

這種模式進行開發,上述例子開放了一個 GET /users 的訪問端點

那若是進行注入呢:

class UserController {
    @Config() config;
    
    @Request()
    index(request) {
        this.request.param()
        this.config.get('app.port')
    }
}複製代碼

咱們能夠對屬性,方法,構造函數進行注入

原理是使用裝飾器標記控制器屬性方法等須要注入的參數,而後調用函數的時候從容器中取出(這裏碰到個坑),因爲http服務請求的上下文在回調函數中,因此我綁定了一個回調函數到容器中,須要獲取實例的時候將上下文傳入函數中,生成例如request對象的實例。


提供者

這時候開發的框架,各類服務默認綁定在容器中,與應用類耦合,雖然是框架自帶的服務,可是仍是不夠完美,因此借鑑了提供者的設計模式,將全部服務抽離並設計註冊服務的api,在框架啓動時,自動註冊默認服務。


這樣子,咱們的全部服務與框架底層核心徹底解耦,保證了底層核心的精簡,並具備強大的可伸縮性。


模塊化

既然是一個web框架,使用的時候確定會承載不一樣的業務,因此咱們須要使用模塊化功能拆分業務,提高可維護性,好比能夠設定這個模塊包含了哪幾個控制器(支持通配符),這個模塊須要加載哪些中間件,甚至子模塊功能

因此我就設計了這麼一套方案,使用模塊描述類來定義模塊

module.exports = class ExampleModule {
    // 標示子模塊
    modules = [];
    
    // 標示須要裝載的控制器
    controllers = [];

    // 標示須要加載的中間件
    middlewares = [];
}複製代碼

🤓 good

請求

做爲web框架,確定須要解析請求啊什麼的,既然不是擴展 ctx 屬性,那麼個人方案就是使用 Request 類來解析 ctx, 這樣的好處就是,我能夠解析koactxexpressreqres或者其餘框架的上下文對象,而且這個類是註冊在容器中的,若是你有其餘的解析方案,固然也能夠本身註冊一個,而後隨心所欲(沒錯,IOC容器就是能夠隨心所欲😎)。

響應

生產響應的時候確定也要越方便越好,方便到你只須要在控制器中return就好,能夠return各類類型,除了koa2中的支持的數據類型,還支持直接返回 框架的 View(視圖,即模板)實例或者Response(響應類)實例等等,框架都會自動判斷。

class UserController {
    index() {
        return [{ id: 1 }]
    }
}複製代碼

就是這麼方便,固然不只僅這樣,還有更多強大的功能。

驗證器

我在使用不少框架的時候,驗證請求數據不是很方便,因此也從新設計了一套方案(狗頭),

固然仍是使用裝飾器模式

// 定義一個驗證類,放在指定目錄
class UserPostValidate extends Validate {
    @MaxLength(10) username;
    @Length(1, 20) password:
}複製代碼

而後在控制器中

class UserController extends Controller {
    store() {
        this.request.validate('UserPostValidate')
    }
}
複製代碼

狗頭

寫了很久,先去吃飯了,其實還有不少功能模塊,例如日誌服務、多進程服務、進程間通訊服務、安全相關服務、cookiesession服務等等,有興趣的能夠留言繼續解答,或者出第二篇,下次出點技術類的~~~🐶

倉庫地址: [Github]

固然,框架核心代碼在 framework 這個包,目前還在開發和測試中,優化一些功能和文檔,工具比較low逼,也須要完善,但願有大牛能夠一塊兒開發。

目前已經到 0.8.x 版本,已經歷時半年(第一個npm包提交開始),離第一個穩定版不遠了!!!!正在快車道中,但願明年儘快開放 1.0 版本服務大衆。

也但願你們能夠嘗試下提供各類意見反饋,因爲目前就一我的開發,bug確定很多,cli工具方面已經好久沒更新了,準備下一步完善工具,若是須要體驗的(工具萬一有bug),直接clone daze 倉庫就能夠。

而後,但願你們不要吝嗇本身的 star 🐶🐶🐶🐶🐶🐶🐶🐶給個鼓勵~~~~

最後,祝你們新年快樂,新年新氣象 🎉🎉🎉🎉🎉🎉🎉

相關文章
相關標籤/搜索