淺談先後端分離與實踐 之 nodejs 中間層服務(二)

1、背景

書接上文,淺談先後端分離與實踐(一) 咱們用mock服務器搭建起來了本身的前端數據模擬服務,先後端開發過程當中只需定義好接口規範,即可以相互進行各自的開發任務。聯調的時候,按照以前定義的開發規範進行數據聯調即可以了。先後端的職能更加清晰:html

後端 前端
提供數據 接收數據,返回數據
處理業務邏輯 處理渲染邏輯
Server-side MVC架構 Client-side MV* 架構
代碼跑在服務器上 代碼跑在瀏覽器上

這裏分離乾淨了,分工也很明確了,看似一切都那麼美好,but...咱們也很容易發現問題的所在:前端

  1. Client-side Model 是 Server-side Model 的加工
  2. Client-side View 跟 Server-side是 不一樣層次的東西
  3. Client-side的Controller 跟 Sever-side的Controller 各搞各的
  4. Client-side的Route 可是 Server-side 可能沒有

也就是說服務端和客戶端各層職責重疊,你們各搞各的,很難統一具體要作的事情。而且可能會伴隨着一些性能上的問題。最具體的表現就是咱們經常使用的SPA應用:node

  1. 渲染,取值都在客戶端進行,有性能的問題
  2. 須要等待資源到齊才能進行,會有短暫白屏與閃動
  3. 在移動設備低速網路的體驗奇差無比
  4. 渲染都在客戶端,模版沒法重用,SEO實現 麻煩

緊接着,咱們代碼量愈來愈大,咱們須要校驗的表單也會愈來愈多,有時候,前端提交須要校驗一次表單。
服務端任須要進行校驗來達到數據的可靠性;前端的路由可能在服務端並不存在....等等這一系列重用性的問題。因此咱們以前的重構可能須要更深層次的思考。git

2、開始重構

在開始重構以前,咱們須要對先後端界線作一個劃分,也就是說什麼是屬於前端的範疇,什麼是屬於後端的範疇,最傳統的先後端劃分多是這樣的:github

image.png
image.png

那麼問題來了:咱們先後端劃分的接線,是依照工做職責來劃分的先後端;仍是依照硬體環境劃分的先後端?自從了nodejs以後,咱們能夠從工做職能上從新定義先後端的範疇:web

image.png
image.png

能夠看到,這裏的前端比以前多了個nodejs,也就是在先後端之間咱們構建了一個 nodejs 服務做爲中間層!
爲何咱們選擇的中間層是nodejs呢?由於咱們把中間層歸在了前端的範疇,那麼對前端小夥伴來講,nodejs畢竟仍是個js,那麼從語法角度來講,上收起來應該沒有什麼問題。其次開發轉移成本也想對較低,沒必要來回切換語言的邏輯和語法:ajax

  1. 前端熟悉的語言,學習成本低
  2. 都是JS,能夠先後端複用
  3. 體質適合:事件驅動、非阻塞I/O
  4. 適合IO密集型業務
  5. 執行速度也不差

好了,提早說了這麼多東西,那麼這個中間層能給咱們帶來什麼了?要知道引入nodejs的開發成本也是很大的,首先就是多了一層服務,多的不說,單憑傳輸時間,就多了一層的傳輸時間啊!下面咱們來研究一下什麼應用場景下的nodejs能給咱們帶來利大於弊的東西。後端

3、開始中間層之旅

引入nodejs以後,咱們來從新劃分一下先後端的職能:瀏覽器

image.png
image.png

這個就是中間層nodejs的主要思路,下面咱們來看一下常見的業務場景:性能優化

1. 接口數據可靠性修復

有的時候服務端返回給咱們的數據可能並非前端想要的結構,全部用到的展示數據都是後端經過異步接口(AJAX/JSONP)的方式提供的,前端只管展示。可是後端常常提供後端的數據邏輯,在前端還須要去處理這些數據邏輯。好比我再開發一個功能的時候,有時候會碰到這樣的問題:

image.png
image.png

image.png
image.png

服務端返回的某個字段爲 null 或者服務端返回的數據結構太深,前端須要不斷寫這樣的代碼去判斷數據結構是否真的返回了正確的東西,而不是個null 或者undefined:

if (params.items && params.items.type && ...) {
   // todo
}複製代碼

對於這種狀況,咱們前端其實不該該去重複校驗數據的格式,這也本不該該是瀏覽器端js須要作的事情。咱們能夠在中間層作接口轉發,在轉發的過程當中作數據處理。而不用擔憂數據返回的問題:

router.get('/buyer/product/detail', (req, res, next) => {
  httpRequest.get('/buyer/product/detail', (data) => {
    // todo 處理數據
    res.send(data);
  })
})複製代碼

2. 頁面性能優化 和 SEO

有點時候咱們作單頁面應用,常常會碰到首屏加載性能問題,這個時候若是咱們接了中間層nodejs的話,那麼咱們能夠把首屏渲染的任務交給nodejs去作,次屏的渲染依然走以前的瀏覽器渲染。(前端換頁,瀏覽器端渲染,直接輸入網址,服務器渲染)服務端渲染對頁面進行拼接直出html字符串,能夠大幅提升首屏渲染的時間,減小用戶的等待時間。這種形式應用最廣的好比 Vue 的服務端渲染,裏面也有相關的介紹。
其次對於單頁面的SEO優化也是很好地處理方式,因爲目前的ajax並不被搜索百度等搜索引擎支持,因此若是想要獲得爬蟲的支持,那麼服務端渲染也是一種解決方法。(PS:若是以爲服務端渲染太麻煩,我這裏還有一篇介紹處理SEO的另外一種思路處理 Vue 單頁面 Meta SEO的另外一種思路能夠參考)

3. 淘寶常見的需求解決方案

需求:在淘寶,單日四億PV,頁面數據來自各個不一樣接口,爲了避免影響體驗,先產生頁面框架後,在發起多個異步請求取數據更新頁面,這些多出來的請求帶來的影響不小,尤爲在無線端。

解決方案:在NodeJS端使用 Bigpiper 技術,合併請求,下降負擔,分批輸出,不影響體驗。同時能夠拆分大接口爲獨立小接口,併發請求。串行 => 並行,大幅縮短請求時間。

4. 更多可能

image.png
image.png

結語

這裏只是提供問題的一種解決思路,仍是那句話:一切看應用場景。若是你對本文內容有別的意見也歡迎一塊兒交流探討。

關於

做者:monkeyWang

本人主頁:monkeyWang

本文部分圖片斷落參考文章: 淘寶先後端分離實踐

微信公衆號:會不按期推送前端技術文章,歡迎關注

image.png
image.png
相關文章
相關標籤/搜索