前端后端分離解決方案

tl0562 8年前發布 | 26K 次閱讀 HTML 前端技術

來自: http://zhenhua-lee.github.io/react/goku.html

0.Goku

Goku是《七龍珠》的主人公孫悟空,神通廣大,解決世間存在的問題。同樣,嘗試前后端分離,也希望可以解決目前前端開發中存在的痛點。

1.基本思路

整體上使用MVC的架構,但跟Angular不同(雙向綁定),數據是單向流動的,數據單向流動有如下的好處:

  • 數據具有更好的可預測性,view層的變化一定來源于model
  • 性能上更優

MVC各層使用的基本技術:

  • view: 使用react作為view層渲染,這里面的渲染分為node端、瀏覽器端。react的虛擬DOM、專注于UI、單向流動的特點,是解決頁面性能的一把利器。
  • controller: react-router是建立在 history 上,用于實現頁面單頁面應用,同時也方面地進行路由管理。通過react-router可以方面地進行請求的分發處理。
  • model: 使用了redux實現數據的流動,同時配合immutable.js來解決state的不可變性,避免引用帶來的副作用。

2.整體架構

Goku整體架構主要存在四個實體: 瀏覽器(browser)、nginx、node中間層、后端sever。跟傳統的網站架構相比,多了一層node中間層,該層也是Goku的核心。

3.詳細描述

3.1 瀏覽器

因為使用了react-router,所以整個系統就是一個單頁面應用(SPA):

  • 當頁面初始化時,首屏數據已經渲染完成,直接展示處理
  • 次屏數據,需要通過ajax異步獲取數據,然后在瀏覽器端完成渲染

這里面存在一個問題:如果保證前后端渲染的一致性? 即要求react的 data-react-checksum 前后結果保持一致。

  • 首屏數據需要通過 JSON.stringify(datat) 傳遞給頁面
  • 避免生成動態內容,例如存在 new Date() ,則這個時間在node和browser渲染后就會造成不同

3.2 nginx

nginx已經非常流行,起到請求分發和負載均衡的作用。這里,通過nginx將不同的請求,分發到不同的服務器上:

  • url請求統一分發到node server,從其中獲取前端的靜態資源
  • api請求,直接發送到后端服務,當然也可以通過node server來中轉

3.3 node server

node server就是一個中間層,起到兩個作用:

  • 前端靜態資源的管理
  • 首屏數據的渲染

具體來說,可以分為如下幾個功能點:

3.3.1 路由匹配

思路: 根據請求的URL + react router的router配置信息,得到匹配的component

import { match, RoutingContext } from 'react-router';
import routes from './routes';

serve((req, res) => { match({ routes, location: req.url }, (err, rediction, renderProps) => { if (...) { res.status(200).send(htmlStr); } }) })</pre>

3.3.2 獲取首屏數據

思路: 每個URL均有指定的首屏數據,通過Promise.all并發地發布異步請求,當所有數據都拿到后,執行回調函數

Promise.all([promise1, promise2, ..., promisen], (vals)=> {
  ...
  const initialState = val;
  const store = createStore(reducer, initialState);
})

3.3.3 靜態化渲染

思路: 使用react的 renderToString 得到靜態化數據

Promise.all([promise1, promise2, ..., promisen], (vals)=> {
  ...
  const initialState = val;
  const store = createStore(reducer, initialState);
  ...
  const props = { store, ... };
  str = React.renderToString(App, props);
});

3.3.4 數據mock

思路: 每個api跟一個相應的js文件對應起來,js文件通過 mockjs 的數據模板完成數據的mock

3.3.5 返回完成html

思路: 將3.3得到的字符串 str 與html的其他內容(例如 mta 、 <script> )、首屏數據( initialState )拼接得到一個完整的html字符串

3.4 browserify打包構建

通過使用browserify的transform function、plugin進行了功能的拓展,可以完成更多的事情。同時使用watchify來watch文件的變化。

3.4.1 require css文件

思路: 使用css-modules,將css文件映射成一個js對象和css線上文件,在jsx中直接require css

3.4.2 code split

思路:為了避免將所有的文件打包成一個js文件,使用browserify的plugin機制(使用factor-bundle插件)來進行js文件的拆分,然后使用react router的getComponent、getChildroutes完成動態加載。

3.4.3 模塊打包

通過3.4.2, 將文件打包成一個公共js文件、若干個業務文件,同時采用樹形結構來進行文件的組織。類似于: https://github.com/rackt/react-router/tree/master/examples/huge-apps

3.5 監控體系

為了保證node服務的穩定性,需要進行一些監控,保證服務的穩定性,包括:node進行管理、falcon機器監控、sentry收集瀏覽器異常、性能監控、權限管理、日志管理

3.6 node與后端服務通信

目前是通過一個內網域名進行訪問,當然這種方式存在一些問題:多一次域名解析、訪問協議等。

3.7 后端服務

在這種架構下,后端服務只提供API,不再涉及后端模板、URL controller,后端同學可以專注于數據處理,不需要留意頁面展示,前后端分工更加明確。

4.最近的思考

4.1 前后端分離的代價與收益

先說感受最深的收益吧:

  • 速度: 前端開發不再依賴于后端服務、后端數據,這樣可以加快開發速度
  • 職責: 前后端分工更加明確,前端側重于數據展示、交互處理,后端側重于數據處理、數據存儲

代價:

  • 復雜: 多了一個中間層,造成整個架構變得更加復雜
  • 維護: 為了node的穩定、可靠,需要投入大量的時間用于node服務的維護
  • 沖突: 對后端是一個挑戰,開發前期后端根本無法查看頁面,需要耐心解釋
  • 性能: 在首屏渲染的時候,node服務需要訪問后端服務,肯定存在性能上的損失

針對上述問題,個人認為,目前前后端分離適合于一些訪問量不大的內部系統,而對于大pv量的頁面,還是采用傳統的兩層架構(B/S)。

4.2 前端工程師的發展方向

  • web應用: 隨著云計算的發展,越來越多的應用將網絡化(例如現在創業紅海Sass應用),這樣前端工程師就需要面對越來越復雜的業務場景
  • 數據可視化: 這跟大數據有很大關系,這個方向的難點在于圖形學上的內容
  • 移動化: 移動互聯網時代已經來臨,H5開發越來越多,很多公司的戰略是移動優先
  • 全端化: Andriod、IOS、FE均工作于客戶端,隨著react native的出現,三者有融合的趨勢
  • 全棧化: 目前的前后端分工有好處,但是也造成了很多不必要的溝通,同時人為地將整個網站開發割裂開來,回歸全棧開發也是一個趨勢
  • </ul> </div>

 本文由用戶 tl0562 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!