基于 React 的前端項目開發總結

hans511002 8年前發布 | 37K 次閱讀 React 中間件

技術選型

我們的項目主要選用以下技術開發,再配合一些其它輔助工具。

  • react

  • react-router

  • redux

  • react-redux

開發及線上環境

開發環境

由于項目是前后端分離的,所以我們需要一套完整的開發環境,需要包括以下功能:

  • 數據 Mock

  • Webpack 實施編譯刷新

  • 方便前后端聯調

基于這些需求,我們基于 Express, Webpack, Webpack-dev-middleware 搭建了這套完整的開發環境。

可以看到,瀏覽器所有的請求都被本地的 Node.js 服務攔截。對于靜態資源請求,都委托給 webpack-dev-middleware 來處理,對于接口請求根據不同的環境來決定要做的操作。

本地開發

當 ENV = 'development' 時,也就是開發環境,那么就直接讀取本地的 mock 數據來渲染頁面。

前后端聯調

當 ENV = 'api' 時,也就是我們認為的聯調環境,這個時候對于接口請求由 node.js 轉發到需要聯調的真實后端服務地址上,從而避免直接調用所產生的跨域問題。

這樣就可以直接用本地開發代碼和后端聯調,能大大提高效率,省去了每次需要往服務器上構建部署的步驟。

線上環境

前后端是分開部署的,所有的靜態資源都放在 CDN (example.cdn.com)上面。

也就是說我們的頁面在 example.cdn/index.html 這里,但是請求的接口在 example.163.com/api/xxx,我們肯定不能讓用戶去直接去訪問 example.cdn.com/index.html,這樣不合理,而且由跨域問題存在。

那么訪問 example.dai.163.com 的時候,怎么拿到我們的 HTML 頁面呢?

看下圖:

在客戶端和后臺服務之間架設一臺 Nginx, 我們訪問的 example.dai.163.com 有兩種請求:

  • HTML 頁面資源

  • 接口請求

這兩種請求都先經過 nginx,在這里做判斷,如果是頁面請求那么由 nginx 轉發到 CDN, 否則交給后端服務來響應接口請求。

拿到頁面以后,其它所有的 css, js 等靜態資源都是直接請求到 CDN ,這里沒什么說的。

數據流轉

我們是借助 redux 來管理數據流的。

基于 React 的前端項目開發總結

我們來看這張圖。

首先,通過 middleware 和 reducer 生成 store , 然后獲得項目的初始 state ,通過初始 state 去渲染頁面的初始狀態。

以 Home 頁面為例,首先 Home 通過 react-redux 提供的 connect 方法拿到初始 state 作為 Home 的 prop 傳遞給 Home . 而 Home 由多個不同的子組件組成,這些組件的需要數據再由 Home 通過 props 傳遞給自己的子組件。

當 Home 的初始狀態加載完畢后,我們需要向后端請求去拿去一些用戶數據。這時,我們分發一個下面這種格式的 action :

{
  types: ['home/start','home/success','home/failure'],
  payload: {
    api:
    ...
  },
  meta: {
    isApi: true
  }
}

所有的 action 都會按照我們制定的循序通過一個個 middleware .

在這里,我們的 action 會被 callApiMiddleware 通過 meta 里面的 isApi 標識命中,并去做相應的事情。

比如在這個中間件里面,我們去做了真實的接口請求,在請求成功或失敗的時候分發對應的 action ,以及做一些統一的業務邏輯。比如我們對后端返回的接口中 code 值有統一的約定,假設 1 為成功, 2 為失敗, 3 為未登錄。那么我們就可以在中間件中去處理這些業務邏輯。

當請求成功,并渲染頁面后,假設用戶點擊了一個按鈕,這個按鈕需要喚起 native 的一些功能,比如說拍照。那么我們分發一個喚起拍照功能的 camera/start 的 action :

{
  types: ['sdk/start','sdk/success','sdk/failure'],
  payload: {
    command:
    ...
  },
  meta: {
    isSDK: true
  }
}

同樣的道理,這個 action 會被 EpaySDKMiddleware 所識別并處理,在調起 native 的時候, 為了保證安全性,我們需要向后發起一個請求去拿簽名,這個時候就可以在 EpaySDKMiddleware 里面分發一個接口請求的 action ,那么這個 action 同樣需要走一遍所有的 middleware . 那么這個接口請求的 action 就會像上面的流程一樣,通過 callApiMiddleware 去處理。

中間件的存在,使整個流程變得非常清晰,接口的請求的中間件就只做接口請求,調用 native 接口的中間件就只做對 native 的調用,當對 native 接口的調用需要做后端接口請求的時候,去分發一個 action 走接口請求的中間件。

每個中間件只專注于自己的事情,既方便后續的維護,同時也提供了一個很好的拓展方式。

一個例子

假設我們由如下的一個路由配置。

{
    component: App,
    path: '/',
    onEnter: initLogin(store),
    indexRoute: {
      getComponent(nextState, cb) {
        require.ensure([], require => {
          cb(null, require('../views/Home').default)
        }, 'Home')
      },
      onEnter: initHome(store)
    },
    childRoutes: [
      createActivateRoute(store),
      {
        path: 'test',
        indexRoute: {
          getComponent(nextState, cb) {
            require.ensure([], require => {
              cb(null, require('../views/Test').default)
            }, 'Test')
          }
        }
      },
      ...
    ]
}

那結合 react-route 我們來看一個完整的流程。當我們瀏覽器里面輸入 example.dai.163.com/index.html/#/ 的時候。

首先,通過最上面 線上環境 一節提到的內容,拿到頁面需要 html,css,js.

然后渲染 Provide 和 Router 組件,分別提供 store 的注入和路由的控制。

此時觸發根路徑的路由匹配,然后加載根組件 APP , 然后根據路由匹配規則匹配到 IndexRouter , 加載 Home 組件。

后面的事情就和前面數據流轉一節講的是一樣的了。

總結

在前后端完全分離的基礎上,借助一套完善的開發環境,可以大大提高的我們的開發效率,降低前后端聯調的成本。

同時借助于 Redux 思想,實現單向數據流,讓我們可以實現一個非常清晰的數據流向。并且,借助于中間件,我們可以更加有效的控制數據流轉的過程。為后面項目的擴展提供無限的想象空間。

 

來自: www.kisnows.com/2017/05/12/react-base-project-summary/

 

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