前後端分離專案實踐分析

餘二五發表於2017-11-14

一、前言

  • 對nodejs有了些準備,希望多瞭解些後端知識,恰逢公司專案調整,分析了前後端分離的優劣,也做了一個完整的demo演示,同事都覺得靠譜,用了兩個版本的時間,將公司主站專案用nodejs實現了前後端分離,在此和大家分享下,以求共同進步。案例參見 http://www.upopen.cn

二、為何做分離

  • 1、開發體系:架構體系決定了後端重於前端,前端做好靜態頁後,要轉為php或vm等,開發要用eclipce等後端環境工作,一大堆讓前端迷糊的配置,一旦java人員更新了錯誤的檔案,會導致所有人的環境啟動不了,束手無策,只能等待救援。

  • 2、難維護:頁面總是會有phpjsp等非前端程式碼,相互干擾、無法優化,時間越久問題越突出。

  • 3、前後端職責不清晰。

  • 有人會問,分離為什麼不全部走ajax,頁面就不需要任何服務端語言了。但實際場景並非如此,首先有些資料總是要生成頁面時就已經同步獲取的,且全非同步對SEO不利、純html頁面沒有include功能等。

    網上還有其它的理解,大致相同就不列舉了。

三、如何做分離

  • 1、產品設計確定後,前後端人員共同制定開發介面,為方便介面的制定、顯示、測試,使用nodejs+mongodb開發了介面平臺。參見http://www.upopen.cn:8090/interface/index

    功能:制定介面時就直接在interface平臺上新增錄入ActionName、description、 method、 param 及 預設值 等並儲存到mongodb,當後臺開發完成後,直接用在該頁面做介面測試,成功後方可交付,避免聯調過程中的介面反覆。(原本想用interface.upopen.cn 來測試同域名下的專案,但因cookie在不同二級域名下無法共享的問題,暫用了二級目錄,不過已有方案,後續優化)

  • 2、從前端角度考慮系統架構圖如下:

  • 前後端分離架構圖

aa3756e5-d06c-3431-aadf-30733d2d4466.png

  • 訪問入口 NGINX 代理靜態資源到 STATIC 伺服器,其它請求則到 NODEJS。

  • 頁面請求NODEJS直接render,資料相關NODEJS則做預處理,再發到後臺

  • 前端據已定義的介面,通過nodejs+mysql模擬後臺完成資料存取,此處會增加些工作量,但只是為了走通業務流程,模擬後臺資料表定義及邏輯無需嚴謹,只要能正常存取即可,如註冊使用者save to DB,登入驗證read from DB,所以提供模式化的工具、寫法後,新增表、介面,並不會多耗時間,nginx – nodejs – 模擬後臺,即可按實際使用完成所有前端工作。

  • QA單獨測前端時,修改hostIP指向到測試工具。

  • Java開發完成後介面,在 Interface平臺 上驗證所有介面,確認無誤。QA也可以通過Interface測試Java介面

  • nodejs修改config裡的hostIP配置到java,理想情況下,修改此步配置即完成聯調

  • 每個模組的簡略部署如下:

Nginx.conf:
     Location ~ .(jpg|png|css|js ){ //靜態資源代理
          Root /root/static/;
     }
     Location { //其它介面轉發
     Proxy_pass http://upopen.cn;}
…
Upsteam upopen.cn{
     Server http://node.upopen.cn;}
  • STATIC 結構如下:使用require.js做模組化載入工具,有朋友問為什麼不用seajs,還問這兩個優劣,其實前兩年的專案用的都是seajs,此處想試試amd vs cmd,所以就用了require.js ,以目前的使用來看,相互可替代

Core:[核心模組,主要是引入第三方必用、穩定模組]
     Base.js [自定義通用函式]
     Require.js
     Jquery.js
     Bootstrap.js
     Backgone.js
     Socket.io.js
     I18n.js
     …
Public: [業務級公共模組]
     Validate.js [表單驗證模組]
     All.js [所有頁面需要執行的業務js,如登入驗證]
     Zhdoc.js [國際化文字定義]
     Reset.css [樣式初始化]
     common.css
     …
Widget: [自定義元件]
     Dialog: [彈框元件]
          Dialog.js
          Dislog.css
          Imgs: [彈框元件圖片]
     Calendar:[日誌元件]
          Calendar.js
          Calendar.css
          Imgs: [日曆元件圖片]
     …
Module: [業務模組]
     Issue: [靜態模組]
          Index: [首頁]
               Index.js
               Index.css
               Imgs:
          news: [新聞]
               news.js
               news.css
               imgs:
          …
     User: [使用者模組]
          Register: [註冊]
               Register.js
               Register.css
               Imgs:
          findPwd: [找回密碼]
               findPwd.js
               findPwd.css
               imgs:
          …

Nodejs結構主要如下: express 框架

     App.js
     Package.json
     Node_modules:
     Routes:
          Index.js – 路由入口,接收所有請求做轉發,並做許可權過濾、404等
          Issue.js – 接收來自index.js的靜態請求
          User.js - 接收來自index.js的使用者請求,頁面請求render,資料請求轉發
          …
     Views: [使用ejs框架,接收來自 routes 裡的頁面請求]
          Common: [公用模組頁]
               Header.ejs
               Footer.ejs
               …
          Issue: [靜態模組頁]
               Index.ejs
               News.ejs
               …
          User: [使用者模組頁]
               Register.ejs
               findPwd.ejs
               …
          Controls: [業務邏輯模組]
               Config.js –公共配置模組,如hostIP、basePath等,切換環境修改此配置
               User.js - 接收來自 route/user.js的資料請求,向外轉發做邏輯準備
               Tool.js - 封裝常用函式如http.request/mailer/md5等
               Redis.js - redis封裝,對於單體封裝內容比較多的模組,單獨成立一個檔案
               …
          Log: [日誌,採用Log4js,日誌是必須的,頁面開發者常欠缺日誌理念]
         Assets: 結構、使用同 STATIC,不配置nginx時,呼叫此處資源,意義不大
         …
Nodejs + MySql: [模擬後臺模組,相對上面的模組,主要多了DB]
     Db: [資料處理模組]
          Mysql.js – 封裝模式化資料儲存介面,提供最便捷的新增表、介面的方法
  • 按此結構完成前端所有功能,因目前專案較小,部分模組還有細分空間。

四、分離結果如何

  • 1、開發效率更高,在聯調之前,互不干擾,前端開發完成後就是實際可用的程式碼,不需要再轉換成後臺編譯環境,永遠不會被java / php 啟動不成功所困擾。

  • 2、部分需要前後端共同開發的功能,如檔案上傳,通常需要頁面端與接收端都進行相關的開發配置,之前較難定位是誰配置錯誤,現在全部由前端完成,開發、測試都容易定位,上傳成功後,只要向java傳送檔案儲存的路徑即可。

  • 3、完全分清了前後端開發人員的職責,任一方開發完成後都可以提測,實現同步開發、測試。

  • 4、聯調非常簡單,若雙方介面一致,正常情況下只要修改要介面請求IP即可完成切換。

  • 5、問題責任清晰,聯調、測試、預發、上線,每個過程都難免會產生問題,前端、後端、運維三方責任邊界清晰,日誌中記錄nodejs的請求發出,nginx請求接收與轉發、java端請求接收與返回,三處任何一處斷點,都能馬上定位是哪方的問題。

  • 6、前端人員有更高的許可權,頁面端的展示幾乎全由前端實現,但之前一些配置卻受制於後臺,比如常見的模板功能,純html頁面雖可以通過angularjs實現模板,但實際效果卻並不理想,網速差時經常會出現include部分顯示後置、甚至載入不成功的情況,nodejs的ejs框架可以很好的實現這個功能。

  • 另外,據瀏覽器載入不同的css以便實現瀏覽器相容,之前處理通常是頁面載入後,通過js判斷瀏覽器型別,再去載入不同的css檔案,影響渲染效率,並且js判斷瀏覽器型別本身就存在相容問題,用nodejs則可以在render前就完成該判斷,直接用相應的瀏覽器樣式做渲染

  • 7、程式碼複用,驗證模組,頁面端與nodejs端可以直接複用

五、注意事項:

  • 1、前端開發人員不僅需要有紮實的nodejs知識,還要有一定的服務端、運維知識,對http通訊有更深層次的理解,nginx、redis、socket、buffer等技術也要掌握,多多益善。

  • 2、開發之初對功能充分、寬裕的評估,使用初期不要用nodejs過多開發新功能。初次使用,難免會遇到很多意想不同的問題,前端開發人員本身對服務端知識有限,java人員又對nodejs語法不熟,若處理不好會導致專案延期。我原本認為redis同memcached一樣就是connect + set + get,但實際開發時遇到一些考慮不周而產生的怪異問題,延長該部分開發時間,最終導致專案delay。

  • 3、前端開發人員可嘗試用linux系統開發,第一版用win7開發時,npm部分模組的安裝會不順利,如node-canvas在win7上安裝需要6步,而原本在32上已配置成功了,在64位上的系統上又不成功,後來該介面暫由java實現。實際上即使配置成功了,該模組在釋出伺服器的linux系統上也無法使用,需要重新安裝。第二版開發時,我使用了ubuntu,雖然有一定的學習成本,但對後期的效率提升十分有益,多學習一種系統操作,和運維除錯時也更加主動。不過ubuntu下沒有找到做PSD切圖的工具,所以安裝雙系統更合適切換使用。

六、總結:

  • 目前用分離方式做了兩版專案,開發效率提升、協作溝通便捷上有明顯優勢,作為前端也學習了很多新知識、擴大影響範圍,是共贏的。目前使用還較初級,要繼續學習、探索。在此貼出以便和同仁共進步之。

本文轉自 h2appy  51CTO部落格,原文連結:http://blog.51cto.com/h2appy/1851577,如需轉載請自行聯絡原作者


相關文章