egg.js和nestjs使用場景對比

提醒你們:注意文章的時效性,畢竟不一樣的時間節點,框架成熟度不一樣。分享這篇文章主要是但願可以讓你們認清框架的定位和應對的業務場景,框架沒有好壞之分,只有是否適合本身。html

原標題:關於nodejs-web框架的調研java

做者:xingyuzhenode

日期: Feb 25, 2018git

原文: github.com/xingyuzhe/b…github

如下內容實際上是補漏, 算是對1月份一點工做的總結。web

加入了新團隊, 初次接觸, 粗略的查看了一些項目(nodejs server端), 發現存在幾個問題:redis

對於新成立的團隊,存在以上問題能夠理解, 本次是討論和解決第一個問題。typescript

對於集團範圍內而言,同種技術存在多種不一樣規範和框架很正常, 可是對於一個幾十人的團隊而言, 資源有限,仍是集中力量統一一下效率高些, 有鑑於此, 以爲作一個種子項目比較合適: 一個企業定製框架, 共同維護, 同步更新, 信息共享和沉澱最佳實踐。express

跟領導聊了一下, 總結了一下當前狀態團隊對於這塊內容的一些主觀訴求:npm

  1. 框架實現夠簡單, 團隊能全面掌控, 低風險。
  2. 給新手從基礎開始學習的機會, 就是但願除了知足業務需求以外, 團隊也能獲得成長。
  3. 一個企業基礎框架應知足的基本要求: 約束規範、擴展機制、安全、高效業務開發
  4. 最終仍是但願能沉澱出一套本身的輪子

根據上面的要求, 篩選出了eggjsnestjs2個web框架, 其中nestjs是團隊一部分同窗比較喜歡和嘗試使用了的。

首先從外層信息作些調查。

我通讀了eggjs和nestjs的文檔,查閱了一些資料, 簡單對好比下:

-- eggjs nestjs
github stars 7014 4291
github forks 720 250
gitHub dependents 1591/305 0/0
npm search results 565 53+
github contributors 101 31
github core contributors 4(10+) 1(2+)
github releases 49 19
github issues 86/1416 20/347
基礎框架依賴 koa2 express
文檔 業界良心 通常
核心原理 載入-掛載 模塊容器-依賴注入(經過裝飾器和元數據實現)
核心理念 微內核-插件機制 組件樹-裝飾器-流程控制

eggjs的特色和解決的主要問題:

  1. 經過載入代碼-自動掛載代碼到對象的方式解決了處處寫import/require的問題, 再也不須要手動維護模塊之間的依賴關係, 核心就是一個loader, 雖然官方沒有說起, 可是本人開下腦洞猜想, 這個模塊的實現靈感有可能來自於墳頭草已經一人高了的seajs, -_-, 這種掛載模式實現起來簡單粗暴直接高效, 可是一個小問題就是在使用TS編寫代碼的時候, 會影響書寫體驗的流暢度, 畢竟不很OOP。
  2. 微核心 + 插件機制(這個理念其實一直以來都是代碼組織的核心手段, 本人在之前開發播放器和IM客戶端這塊時感同身受), 大部分功能經過插件實現, 從而剝離非核心生命週期功能代碼, 達到解耦/下降思惟負擔的目的; 另一點就是跨模塊API調用比較自由沒有限制, 這個地方帶來便捷的同時也有可能須要必定約束。
  3. 統一約束和規範, 對開發人員強約束, 保證不會出現千人千面的代碼風格和設計。
  4. 種子項目 + 漸進式開發, 能夠沉澱出本身的插件和業務框架、最佳實踐
  5. 針對業務中遇到的常見問題基本都給出瞭解決方案, 插件豐富, 配套齊全
  6. 內部實現了進程間管理和通訊功能
  7. 文檔但是說是比較細緻了, 基本把web這塊涉及到的點都涵蓋了, 僅僅通讀文檔對新手而言都會有很多收穫
  8. 核心開發者較多, 屬於團隊項目, 總體看來比較嚴謹
  9. 沉澱時間較長, 正式發版2年, 實際發展了4年
  10. 明肯定義了agent和app模式, 也實現了schedule功能

nestjs的特色和解決的主要問題:

  1. 經過模塊容器-依賴注入維護組件樹的模式解決了處處寫import/require的問題, 再也不須要手動維護模塊之間的依賴關係, 另外編碼方式與java十分類似。
  2. 組件樹容器模式也達到了解耦效果, 實現方式上很大程度上受angular-module影響, 可是須要指定節點component的依賴關係, 跨模塊調用嚴格依賴於聲明. 其實這塊功能github有獨立的項目專作這個東西, 例如: InversifyJS | bottlejs, nestjs 本身實現了這個模塊。
  3. 統一約束和規範, 對開發人員強約束
  4. 大量使用裝飾器, 這個未支持的特性須要編譯, 對代碼閱讀上可能會提升一些難度
  5. 流程控制上比較細緻, 提出了filter、pipe、guard、interceptor這些明確的概念, 雖然這些工做在正常開發時也會作, 可是明確提出來並制定規範仍是頗有必要的
  6. 明確了Exception Layer的概念
  7. 默認使用/推薦TS開發
  8. 自帶微服務實現
  9. 自帶swagger接口文檔生成功能
  10. 核心開發基本就做者一人, 屬於我的項目, 提交記錄比較難看, 前期的提交很是隨便, 到後期才慢慢改善
  11. 2017年1月立項, 2017年5月發佈第一個正式版本, 尚需時日印證

從上述狀況來看, 2個框架都在123這幾項作了工做, 完成了一個框架所應具有的基本訴求; 整體上看eggjs更加成熟和全面, 配套/生態相對完善的多, 低風險; nestjs則比較青澀和單一, 可是在組件樹、流程控制、錯誤層級處理上有本身的特點, 理念上更加OOP,學習並吸取這些理念是很可取的, 但暫時不建議在覈心產品線上投入使用。

eggjs

詳細閱讀了核心相關代碼, 粗略閱讀了cluster等一些模塊和插件的代碼, 代碼讀起來整體比較流暢, 發現框架的核心實現很是簡單明瞭:

  • 框架基礎依賴一個很是獨立的loader模塊, 功能就是加載代碼文件和掛載函數到指定對象。

  • 框架自己核心類只有6個: koa自己的application, context, response, request, egg自身新增的controller, service 這2個類, 後續全部的掛載動做都在這幾個類上面進行

  • 框架明確了app, framework, plugin3個概念, 依賴方式大概是這樣:

  • 框架啓動的核心流程主要是這樣:

    因爲eggjs本身實現了cluster, 自帶進程管理和進程間通訊功能, 因此egg自身部署時並不須要pm2這個工具, 官方文檔上也對此作了解釋。不過因爲這塊內容的引入(cluster還涉及到schedule、socket等功能),給框架自己帶來了大量額外的代碼和邏輯, 整體提高了框架的複雜度。

    可是有些時候因爲某些緣由並不但願直接使用框架提供的cluster解決方案, 另外我查看了下pm2的API, 也是有進程間通訊的API的, 固然用起來可能沒有自定義實現時那樣自由, 也還沒有據說該API有被普遍使用過, 不過, cluster相關的內容可否做爲一個擴展包, 而不是強耦合進框架核心流程中? 這樣框架自己更加簡單純潔, 或者更容易被接受一些?

    爲此嘗試抽離了eggjs的核心代碼, 目標是僅保留最最核心的代碼(移除cluster等周邊代碼), 具有egg的擴展機制和能正常直接使用eggjs的周邊插件, 結果最後只須要幾百行代碼, 不多幾個文件便可完成。後續在此基礎上整理了一個上層框架, 預想做爲業務項目的基礎框架使用,主要涉及如下一些方面:

    1. 抽離eggjs的核心代碼, 僅保留其插件機制和對應的約束規範
    2. 集成經常使用擴展函數、中間件、插件
    3. 集成多節點/進程下消息推送解決方案示例
    4. 集成schedule定時任務模塊

    以後花了點時間用這個上層框架開發了一個抽獎小項目, 開發體驗還算流暢, 雖然說是草量級項目, 不過也是五臟俱全, 做爲example還挺適合。

    nestjs

    粗略查看了下nestjs的源碼, nestjs的核心其實就是一個IoC模塊管理容器的實現, 這塊內容的邏輯實現做者處理的仍是相對複雜的多, 這裏吐槽下做者的代碼組織方式和略顯隨意的註釋大量的接口引用和糟糕的歷史提交記錄...,真是額外提升了閱讀的難度. TypeScript的加持和做者本人的光環也不能阻擋這一點。言歸正傳, 這裏說下它的核心原理和流程。

    要想理解nestjs的源碼先要理解和掌握如下知識:

    1. ES6的proxy,reflect
    2. TypeScript的decorator
    3. inversion of control (IoC)的基本概念
    4. 必定TypeScript基礎.
    5. 如何經過decorator和元數據實現依賴注入
    • container類: 用於存儲全部模塊
    • scanner類: 遞歸提取出全部模塊並存儲到容器中; 提取出模塊間的關聯關係和模塊自身的各類類以及內部聯繫,並存儲到模塊中;
    • module類: 存儲自身的關聯模塊、組件、可注入類、控制器類
    • injector類: 依賴注入的核心環節, 在全部模塊的內容和關係都被掃描出後, 來建立實例,
    • instanceLoader類: 使用Injector來加載模塊的各類實例, 這個過程很複雜, 伴隨遞歸和各類判斷

    這個IoC容器實現的核心流程是這樣: scanner掃描全部module並提取關係存入module->module存入 container-> injector建立實例(依賴注入)-> instanceLoader加載實例

    咱們再拿nestjs實現上面eggjs版本lottery的例子, 大概是這樣:

    結合源碼和實際開發體驗來講:

    • eggjs框架自己的模塊管理(擴展機制)很是簡單, 複雜度主要在於cluster這塊內容和爲此配套的周邊設施(命令行工具、調試工具),可是這個複雜度是脫離於核心以外的東西。
    • nestjs的複雜度主要在於IoC模塊管理器這塊的實現上, 實際上這個東西理論上能夠獨立出來, 以此下降框架自己邏輯的複雜度。

    從整體上講, eggjs相對成熟, 更貼合實際開發需求。 nestjs的優點就是在一些細節上的約束和控制以及理念上的新穎(僅相對node-web框架而言), 可是這些並非核心訴求。

    另外eggjs團隊作的工做內容相對於nestjs而言至關的多, 這些與人力、時間資源的投入是分不開的。

最後, 對於想要的新框架的處理結論已經有了:

1 社區模式(節省資源)

  • 直接在eggjs基礎上作一個上層框架, 吸取nestjs的一些優勢, 做爲插件/擴展內容去完善框架自己.

2 造輪子模式

  • eggjs插件機制 + nestjs流程控制 + component模式(可選) => 新輪子

3 所應具有的特性

  • 約束規範
  • 沉澱/擴展模式
  • 模塊依賴管理
  • 集成typescript開發環境
  • 集成API文檔輸出方案
  • 環境配置
  • 多節點/cluster解決方案
    • socket.io
    • schedule
  • 集成經常使用插件功能
    • logger
    • cookie
    • session
    • security
    • i18n
    • redis
    • sequelize
    • multipart
    • oauth
    • onerror
    • passport
    • view
    • role
    • crypto
  • 定義控制流/數據流約束規範
    • schema
    • pipe
    • interceptor
    • guard
  • migration
  • 微服務
  • 錯誤分級
  • 監控
  • 測試用例/代碼覆蓋率
  • 調試
  • 壓力測試

補充: 隨着各類工具的發展, 加上eggjs使用也有一段時日,最初一些模糊的預感變得清晰: 1 egg內置cluster模式帶來的額外麻煩太多, 如今各類配套工具逐漸完善, 這個功能並無什麼用

2 egg模塊隔離度不夠但矛盾的是有時候又有限制, 簡單的說就是代碼組織模式上做爲框架不夠好, 須要自行定製上層規範; egg的是plugin模式, 相對於nest的component模式仍是不夠用;

3 egg的ts開發的流暢度差那麼一點

4 實際的項目, 須要各類配套設施、工具、系統的協做聯合,框架只是一個組成部分, 就應該只作它應該作的事就能夠了

各有優劣, 訴求不同, 選擇就不同: 1 eggjs: 短平快穩,上手極快, 文檔完善,配套齊全, 能極大縮短工期。 2 nestjs: 有點追求, 複雜度高的協做項目, 核心訴求是代碼組織模式的

以前egg很好的知足了咱們的訴求, 可是下一個項目, 會考慮使用nestjs或者自行開發框架(足夠閒的話)。

egg官方維護者atian25的評論:點擊詳見

atian25補充下幾點:

  • Cluster 裏面並無 schedule

  • Socket 那個是爲了實現高級的 IPC

  • Cluster 仍是很建議使用的,若是有什麼特殊的定製需求,何不如提下 RFC/ISSUE 你們討論下

  • egg-core + egg-cluster 才成爲 egg,你要是想定製,能夠相似 egg-core + my-cluster(雖然不建議)

  • 框架複雜度其實反而是下降了,由於 PM2 的代碼比 egg-cluster 複雜多了

  • Egg 的定位是框架的框架,跟 thinkjs/sails/nest 這些是無法直接對比的,由於不是一個層面的概念。就像你只能對比 Express 和 Koa,而不能對比 nest 和 Koa,由於 nest 是在 Express 之上的封裝。

    基於 Egg 封裝的針對某個領域的上層框架,才能對比。譬如徹底能夠用官方的 TS 方案,再封裝集成幾個裝飾器,成爲一個上層框架。就能夠拿來對比了。

相關資料

Egg & Node.js 從小工坊走向企業級開發

選擇JavaScript開源庫時,你須要考慮這些問題

12個因素

關注公衆號,發現更多精彩

相關文章
相關標籤/搜索