基於 Node.js 先後端分離的一點思考

hello~親愛的看官老爺們你們好~有一段時間沒寫文章了,最近忙於爲一個對內的數據可視化平臺進行徹底的先後端分離。原來的項目是一個基於 Vue 的單頁應用,重構後接入 Node 做爲中間層,達到徹底的先後端分離。前端

因爲項目相對簡單,成本並非過高。下文將簡單介紹一下使用的技術棧與分離後的收益,重點是對基於 Node 作先後端分離的一點思考。數據庫

背景

大約是去年11月底入職新東家,接手一個僅 對內 的數據分析系統。新入職固然是但願作出點成績,在更改部分 UI 與優化部分功能以後,發現頁面性能仍是比較低。排查後發現獲取數據的接口沒有緩存,也不是基於 RESTful 的,瀏覽器緩存徹底不起做用。期間也經歷了後端修改接口,前端代碼大面積修改的狀況。json

基於後端同窗不熟悉前端機制,我也抱着方便往後搞事情的心態,在屢次滾地板以後,部門 Leader 贊成接入 Node 做爲中間層。後端

技術選型

在肯定接入 Node 後,首先要作的就是技術選型。Node 通常就是在 ExpressKoaEgg 中選。在中間件的使用上,我的偏好 Koa ,於是只好和 Express 說再見了 。Egg 是在 Koa 上做了強約束,規定代碼編寫、目錄結構等。瀏覽器

選型時我與前端 Leader 討論了無數次,他認爲 Egg 約束太多,擴展性較差,如若出現框架底層的 Bug 則難於處理,於是偏向於使用 Koa。這樣的顧慮十分合理,然而對於如今的項目而言,不太可能有功能會超出 Egg 所提供的,反而 Egg 所提供的功能能爲項目搭建與維護減小很多的成本。至於約束,我的認爲這反而是一件好事,必定程度上解決了多人開發時代碼的組織問題。緩存

考慮再三後,決定使用 Egg 做爲 Node 的框架。安全

分離收益

因爲項目不算十分複雜,接入的過程算是波瀾不驚。惟一的麻煩是工期比較緊,於是分兩步走:一期先接入 Node,全部頁端請求原樣轉發 Java,返回的結果原樣轉發頁端。二期對數據獲取的接口進行整合與優化以提高性能。完成後收益仍是客觀的,貼兩張圖展現下成果。數據結構

原來某頁面的性能(全部請求都是 Post 的):架構

接入 Node 相同頁面的性能(轉爲方法爲 Get):框架

能夠看到,不管是數據下載量仍是響應時間等指標,耗時均有下降。固然,這是創建在接入 Node 後我對接口進行了整合與緩存優化等措施後的對比。若是都是首次訪問,公司內網 WiFi 環境下與原來的性能會有稍差一點,總體加載時間略高於 Java 直出50ms不到。也用過 Chrome 模擬弱網環境,耗時與 Java 直出基本一致。

並且開發體驗上也比以前舒服得多,算是達到了接入 Node 前定下的目標:接入後在支持相同功能的狀況下性能提升30%;在相同的開發時間內,完成相同的需求,但有更好的開發體驗及更好的頁端性能。

小結一下,前端的一切優化都是在模板與獲取模板所需數據上進行優化,使用 AngularReactVue 等框架構築的單頁應用,解決了模板的問題,能夠再也不讓後端去動咱們的模板。可是獲取所需數據仍依賴於後端,很多單頁應用交互上已經足夠複雜,若是還需維護一套複雜的獲取與整合數據的邏輯,仍是十分頭疼的。於是多接入一層 Node 處理數據的獲取與整合,盡最大努力去優化頁端的請求接口,讓頁端專一於交互,在條件成熟的狀況下,是十分值得的。

思考

如若就爲了推廣 Node,本文應該是把上面的步驟寫詳細,小結完就該結束了,這和不少大佬的實踐文章一致(固然我寫得不夠好~)。然而和兩位 Leader 的討論過程當中,感謝他們對 Node 技術抱有懷疑,提出了很多有意思的問題,結合我本身的思考,整理成提問形式呈現給你們。

爲什麼接入 Node 做爲中間層,和公司現行的 PHP 有何區別?

沒有區別!事實說,Node 能作的 PHP 同樣能作。那麼問題就轉換爲 Node 的意義是什麼,爲什麼擯棄公司相對成熟的 PHP 方案而轉向 Node

我認爲後端服務主要是穩定爲主,業務調整不會特別頻繁。而對於前端而言,業務頻繁調整簡直司空見慣,若是先後端耦合在一塊兒,頻繁讓後端發版不是可取之策。同時,先後端對數據結構的要求及對其控制的粒度也大不相同。寫得好 PHP 的同窗不必定寫得好前端,寫得好前端的同窗不必定寫得好 PHP。對於專業的領域,仍是應該由專業的人去作,讓前端控制整個模板及模板依賴的數據,對提升項目質量有很大的幫助。說句玩笑話,後端就搞搞數據庫,吐吐 json 就好,前端就拿一下數據,切切頁面就好。

進一步而言,前端若要接入 SSR 之類的功能,Node 還真比 PHP 有優點得多,也算是爲往後搞事情作鋪墊吧。

接入 Node 後性能會有多大提升?

不必定有提升,甚至有降低。此問題是我一期完成以後,測試頁端性能時發現的。測試時,Node 除了將全部的需求原樣轉發外,還加了協商緩存,然而響應時間卻更慢了。

接入前(爲 Post 請求):

接入後(爲 Get 請求):

正常來講,獲取 10k 左右的數據時,協商緩存如若命中即返回 304,省略了下載的過程,理應更快的。經過打點,發現 Node 轉發請求耗時額外增長 10ms 左右,然而在全公司內網 WiFi 環境下,總體下載時間不到 160ms。

於是引入 Node 不必定會有性能的提升,反而會由於多引入一層,而致使性能耗損。在對內的項目中或性能尚可的項目中,提升性能不足以成爲接入 Node 的關鍵理由。換句話說,接入 Node 以後,在優化頁端請求以前,並不可能爲應用性能帶來飛躍。

這個問題也算是我對 Node 態度轉變的起點,開始從無腦支持接入 Node 到辯證地推敲,也引出以後的的問題。

接入 Node 有什麼弊端?

前端的能力越強,意味着責任越多。例如以前多是 Java 作的安全防禦,可能就會下沉到 Node 端,這對大多數前端同窗而已都是比較陌生的領域。

投入的成本與產出也是值得商榷的事情,畢竟 Node 再貼近前端,也始終是屬於後端的領域。先後端思想不太同樣,用前端的思惟寫後端,極可能寫出十分糟糕的代碼,輕則影響性能,重則內存泄漏。接入 Node 層後它反而成爲拖累,相信你們也不肯看見。

畢竟 Node 對於很多公司而言是比較新的領域。儘管可能知道接入 Node 好處很多,但如何接入,接入後它能作什麼,你們可能比較模糊。如何花最少的代價,平滑地接入 Node 的同時,最大限度的複用現有架構,也是個很多的挑戰。

既然如此,沒有 Node 適用的場景嗎?

有。正如前文所說,Node 的意義是在於讓前端掌握模板與模板所依賴數據,不妨從這兩方面去進行考慮。如若重 SEO 的同時,頁面交互相對複雜,這時候接入 Node 做爲中間層,我認爲就是最佳實踐。

其次是後端架構不斷演變,開始轉向微服務化以後,前端感到接口碎片化開始帶來很多麻煩後,就應該考慮接入 Node 整合接口了。

總的來講,何時接入 Node, 有點像何時引入 ReduxVuex。當你感受到麻煩後,只要你知道還有這個選項,天然而言地就會想到用它。

小結

綜上所述,在如下場景中,我認爲接入 Node 是最佳實踐:

  • 重視 SEO 且交互複雜。
  • 後端微服務化,前端須要整合接口。
  • 前端主導的項目,須要用到最新技術,如 SSRPWA 等。

如若只是性能問題,引入 Node 不必定會有改善,須要根據實際狀況進行分析。至於後端的接口設計太醜陋、返回的數據結構不符合前端使用等問題,在應用規模不大的狀況下,其實都是能夠和後端同窗進行溝通的,以此接入 Node 不必定是最佳的實踐,須要好好思量。

可是,堅定反對只是由於現有架構比較熟悉而不肯改變,始終抱着錯誤的方案不去解決的作法,這絕對是捨本逐末。我始終認爲,只要是對的事情,儘管過程再艱難,亦應該朝着對的方向前進。

以上是我的的一點淺見,感謝各位看官大人看到這裏。知易行難,但願本文對你有所幫助~謝謝!

相關文章
相關標籤/搜索