對目前的web來說,前后端分離已經變得越來越流行了,越來越多的企業/網站都開始往這個方向靠攏。那么,為什么要選擇前后端分離呢?前后端分離對實際開發有什么好處呢?
為什么選擇前后端分離
- 在以前傳統的網站開發中,前端一般扮演的只是切圖的工作,只是簡單地將UI設計師提供的原型圖實現成靜態的HTML頁面,而具體的頁面交互邏輯,比如與后台的數據交互工作等,可能都是由后台的開發人員來實現的,或者是前端是緊緊的耦合后台。比如,以前淘寶的Web基本上都是基於MVC框架webx,架構決定了前端只能依賴后端。所以他們的開發模式依然是,前端寫好靜態demo,后端翻譯成VM模版,這種模式的問題就不說了,被吐槽了很久。
- 而且更有可能后台人員直接兼顧前端的工作,一邊實現API接口,一邊開發頁面,兩者互相切換着做,而且根據不同的url動態拼接頁面,這也導致后台的開發壓力大大增加。前后端工作分配不均。不僅僅開發效率慢,而且代碼難以維護。而前后端分離的話,則可以很好的解決前后端分工不均的問題,將更多的交互邏輯分配給前端來處理,而后端則可以專注於其本職工作,比如提供API接口,進行權限控制以及進行運算工作。而前端開發人員則可以利用nodejs來搭建自己的本地服務器,直接在本地開發,然后通過一些插件來將api請求轉發到后台,這樣就可以完全模擬線上的場景,並且與后台解耦。前端可以獨立完成與用戶交互的整一個過程,兩者都可以同時開工,不互相依賴,開發效率更快,而且分工比較均衡。
如何做到前后端分離
(以下的內容都是基於我們的電影購票網站來討論的)
前端的技術框架是: vue全家桶+nodejs+express(實現的是單頁面(SPA)應用)
首先,先分清楚前后端的工作
- 前端的工作:實現整一個前端頁面以及交互邏輯,以及利用ajax與nodejs服務器(中間層)交互
- 后端的工作:提供API接口,利用redis來管理session,與數據庫交互
我們項目的整一個架構如下:
接下來進入正題,如何實現前后端分離
- 一般來說,要實現前后端分離,前端就需要開啟一個本地的服務器來運行自己的前端代碼,以此來模擬真實的線上環境,並且,也是為了更好的開發。因為你在實際開發中,你不可能要求每一個前端都去搭建一個java(php)環境,並且在java環境下開發,這對於前端來說,學習成本太高了。但如果本地沒有開啟服務器的話,不僅無法模擬線上的環境,而且還面臨到了跨域的問題,因為你如果寫靜態的html頁面,直接在文件目錄下打開的話,你是無法發出ajax請求的(瀏覽器跨域的限制),因此,你需要在本地運行一個服務器,可是又不想搭建陌生而龐大的java環境,怎么辦法呢?nodejs正好解決了這個問題。在我們項目中,我們利用nodejs的express框架來開啟一個本地的服務器,然后利用nodejs的一個http-proxy-middleware插件將客戶端發往nodejs的請求轉發給真正的服務器,讓nodejs作為一個中間層。這樣,前端就可以無憂無慮的開發了
- 由於前后端分離后,前端和后台同時開發時,就可能遇到前端已經開發好一個頁面了,可是卻等待后台API接口的情況。比如說A是負責前端,B是負責后台,A可能用了一周做好了基本的結構,並且需要API接口聯調后,才能繼續開發,而此時B卻還沒有實現好所需要的接口,這種情況,怎么辦呢?在我們這個項目里,我們是通過了mock來提供一些假數據,我們先規定好了API接口,設計出了一套API文檔,然后我們就可以通過API文檔,利用mock(http://mockjs.com)來返回一些假數據,這樣就可以模擬發送API到接受響應的整一個過程,因此前端也不需要依賴於后端開發了,可以獨立開發,等到后台的API全部設計完之后,就可以比較快速的聯調。
為什么要引入nodejs作為中間層
前面的我發的項目結構圖中,已經表明,在這個項目里,我們將nodejs作為中間層,那么,為什么我們要特地引入nodejs呢?直接用java做不就行了嗎?
- 我覺得引入nodejs主要是為了分層開發,職責划分,nodejs作為前端服務器,由前端開發人員負責,前端開發人員不需要知道java后台是如何實現的,也不需要知道API接口是如何實現的,我們只需要關心我們前端的開發工作,並且管理好nodejs前端服務器,而后台開發人員也不需要考慮如何前端是如何部署的,他只需要做好自己擅長的部分,提供好API接口就可以;
- nodejs本身有着獨特的異步、非阻塞I/O的特點,這也就意味着他特別適合I/O密集型操作,在處理並發量比較大的請求上能力比較強,因此,利用它來充當前端服務器,向客戶端提供靜態文件以及響應客戶端的請求,我覺得這是一個很不錯的選擇。
前端服務器如何部署
nodejs前端服務器的職責
- 作為靜態文件服務器,當用戶訪問網站的時候,將index.html以及其引入的js、css、fonts以及圖片返回給用戶
- 負責將客戶端發來的ajax請求轉發給后台服務器
其實前端服務器的部署工作是算比較簡單的,具體有以下兩個點:
- 將開發完的前端代碼,利用webpack打包成靜態壓縮文件
- 在服務器上,利用pm2負載均衡器來執行以下的代碼來開啟服務器:
評論區有人提到有一個不錯的文章,我看了下覺得寫得確實很詳細,大家也可能看一下:https://segmentfault.com/a/1190000009329474?_ea=2038402 (感覺這就是業務與專業的區別哈哈)
(PS:其實也有一個做法,就是用nginx來做反向代理,負責轉發請求,根據客戶端訪問的url把這個請求轉發到不同的服務,比如訪問/api/*的請求,就轉發到后台服務,訪問其它的請求,就轉發到nodejs服務)
以上,就是我對於前后端分離的一些看法,以及一些實踐,如果大家有什么好的想法,歡迎交流。
本次項目代碼的地址為:https://github.com/chenjigeng/filmshopping
另一篇文章大家也可以分享閱讀
前言
最近這一段時間由於Nodejs的逐漸成熟和日趨穩定,越來越多的公司中的前端團隊開始嘗試使用Nodejs來練一下手,嘗一嘗鮮。
一般的做法都是將原本屬於后端的一部分相對於業務不是很重要的功能遷移到Nodejs上面來,也有一些公司將NodeJS作為前后端分離的一個解決方案去施行。而像淘寶網這類的大型網站也很早的完成了前后端的分離,給我們這樣的后來者提供了寶貴的經驗。
同樣,我們的大網盤團隊也早在去年早早就開始了緊鑼密布的准備工作,這目前工作也做的差不多了,現在我就來總結一下在過程中遇到的坑點以及注意事項。
認識前后端分離
在傳統的web應用開發中,大多數的程序員會將瀏覽器作為前后端的分界線。將瀏覽器中為用戶進行頁面展示的部分稱之為前端,而將運行在服務器,為前端提供業務邏輯和數據准備的所有代碼統稱為后端。
由於前后端分離這個概念相對來說剛出現不久,很多人都是只聞其聲,不見其形,所以可能會對它產生一些誤解,誤以為前后端分離只是一種web應用開發模式,只要在web應用的開發期進行了前后端開發工作的分工就是前后端分離。
其實前后端分離並不只是開發模式,而是web應用的一種架構模式
。在開發階段,前后端工程師約定好數據交互接口,實現並行開發和測試;在運行階段前后端分離模式需要對web應用進行分離部署,前后端之前使用HTTP或者其他協議進行交互請求。然而作為一種架構模式,我們在實施的過程中主要對以下四個方面來進行比較和重新認識。
前后端分離大概可以從四個方面來理解:
-
交互形式
-
代碼組織方式
-
開發模式
-
數據接口規范流程
一、交互形式
在前后端分離架構中,后端只需要負責按照約定的數據格式向前端提供可調用的API服務即可。前后端之間通過HTTP請求進行交互,前端獲取到數據后,進行頁面的組裝和渲染,最終返回給瀏覽器。
二、代碼組織方式
在傳統架構模式中,前后端代碼存放於同一個代碼庫中,甚至是同一工程目錄下。頁面中還夾雜着后端代碼。前后端工程師進行開發時,都必須把整個項目導入到開發工具中。
而前后端分離模式在代碼組織形式上有以下兩種:
-
半分離
前后端共用一個代碼庫,但是代碼分別存放在兩個工程中。后端不關心或很少 關心前端元素的輸出情況,前端不能獨立進行開發和測試,項目中缺乏前后端 交互的測試用例。 -
分離
前后端代碼庫分離,前端代碼中有可以進行Mock測試(通過構造虛擬測試對 象以簡化測試環境的方法)的偽后端,能支持前端的獨立開發和測試。而后端 代碼中除了功能實現外,還有着詳細的測試用例,以保證API的可用性,降低 集成風險。
三、開發模式
我們之前的架構屬於傳統的MVC架構,整體沒有進行前后端分離,在項目的開發階段,前端工程師負責編寫HTML,完成前端的頁面設計並套頁面,然后再使用模板技術將寫好的前端代碼轉換為Smarty腳本,同時內嵌一些后端提供的模板變量和一些邏輯操作。應用運行期,將全部代碼進行打包,和后端代碼部署到同一服務器上,同時會進行簡單的動靜態分離部署。
此時,應用的開發流程如下圖所示。
而在實現前后端分離架構之后,前端工程師只需要編寫HTML、js、CSS等前端資源,然后通 過HTTP請求調用后端提供的服務即可。除了開發期的分離,在運行期前后端資源也 會進行分離部署。
前后端分離之后,開發流程將如下圖所示。
通過上面的兩幅流程圖,不難發現,在開發模式上,前后段分離不僅僅只是工程師的分工開發,更重要的意義在於實現了前后端的並行開發,簡化了開發流程
。
四、數據接口規范流程
在開發期間前后端共同商定好數據接口的交互形式和數據格式。然后實現前后端的並行開發,其中前端工程師再開發完成之后可以獨自進行mock測試,而后端也可以使用接口測試平台進行接口自測,然后前后端一起進行功能聯調並校驗格式,最終進行自動化測試。
分離的四個好處
前后端分離模式和傳統的web應用架構相比有很大的不同,到底分還是不分,這還真是個問題。
從目前應用軟件開發的發展趨勢來看,主要有兩方面需要注意:
-
越來越注重用戶體驗,隨着互聯網的發展,開始多終端化。
-
大型應用架構模式正在向雲化、微服務化發展。
我們主要通過前后端分離架構,為我們帶來以下四個方面的提升:
-
為優質產品打造精益團隊
通過將開發團隊前后端分離化,讓前后端工程師只需要專注於前端或后端的開發工作,是的前后端工程師實現自治,培養其獨特的技術特性,然后構建出一個全棧式的精益開發團隊。 -
提升開發效率
前后端分離以后,可以實現前后端代碼的解耦,只要前后端溝通約定好應用所需接口以及接口參數,便可以開始並行開發,無需等待對方的開發工作結束。與此同時,即使需求發生變更,只要接口與數據格式不變,后端開發人員就不需要修改代碼,只要前端進行變動即可。如此一來整個應用的開發效率必然會有質的提升。 -
完美應對復雜多變的前端需求
如果開發團隊能完成前后端分離的轉型,打造優秀的前后端團隊,開發獨立化,讓開發人員做到專注專精,開發能力必然會有所提升,能夠完美應對各種復雜多變的前端需求。 -
增強代碼可維護性
前后端分離后,應用的代碼不再是前后端混合,只有在運行期才會有調用依賴關系。
應用代碼將會變得整潔清晰,不論是代碼閱讀還是代碼維護都會比以前輕松。
需要進行前后端分離的場景
任何一項技術以及架構都不是適用於任何場景,前后端分離同樣也是如此。雖然前后端分離架構能帶來許多的好處,但前提是建立在開發團隊合適的基礎上的。
而我們百度網盤就屬於那種:
-
頁面布局復雜,使用了主題和樣式。
-
需要有較高的頁面渲染效果
-
前端頁面中包含復雜業務邏輯
-
頁面需要渲染的數據量較大
像這種重前端
的應用我們綜合考慮了各種情況,最終決定采用前后端分離架構。
部署方案
前后端分離之后,應用在部署時也需要進行前后端分離。在進行前后端分離方案選擇時,需要結合項目的實際情況和用戶來考慮。
分離之前的架構
前后端分離之前,網盤的后端架構是Nginx服務和后端的PHP服務以及前端的靜態資源都是部署在同一台服務器上。當瀏覽器發起訪問請求時,如何請求的是靜態資源,Nginx直接把靜態資源返回給服務器;如果請求的是頁面或后端服務,則經Nginx將請求轉發到后端的PHP服務器,完成響應后經Nginx返回到瀏覽器。
注:此圖中的Nginx屬於后端機,主要針對前端機Nginx轉發過來的請求進行識別弄轉發給本機的PHP服務;前端機和后端機各有一個Nginx服務。
這個方案比較簡單,易於實現,而且能到達前后端解耦的目的。而且很多公司目前都是基於這種架構或者一定的變形來實現的web應用。
但是對於頁面量比較大,需要有良好SEO的應用來說,此方案缺點也較為明顯。因為 Nginx只是向瀏覽器返回頁面靜態資源,而國內的搜索引擎爬蟲只會抓取靜態數據, 不會解析頁面中的js,這使得應用得不到良好的搜索引擎支持。同時因為Nginx不會進行頁面的組裝渲染,需要把靜態頁面返回到瀏覽器,然后完成渲染工作,這加重了瀏覽器的渲染負擔。
另外,由於這種架構使得前端工程師的工作范圍只局限在了瀏覽器一側,導致在進行一些特殊的性能優化時,前端工程師無法獨立完成,還需要后端開發人員的配合,這也一定程度上影響了雙方的進度。
分離之后的架構
前后端分離之后,我們在原先的架構只上再單獨增加了一個Node Server作為中間層,將前端資源部署到Node Server中。Node Server還實現了一層數據代理服務,負責與提供數據的后端服務進行通信。
並且還在這個基礎上增加並使用了前端機(前端機是對所有的請求進行預處理和負載均衡,然后再轉發給后端機。)的Nginx服務,瀏覽器發起的請求經過前端機的Nginx進行分發,URL請求統一分發到Node Server,在Node Server中根據請求類型從后端服務器上通過RPC服務請求頁面的模板數據,然后進行頁面的組裝和渲染;API請求則直接轉發到后端服務器,完成響應。
前后端分離方案對比
實現和部署
大家分享百度網盤前后端分離中的Node Server基礎架構、前端路由管理、模板數據交互以及運維和環境部署相關內容。
結語
前后端分離並非僅僅只是前后端開發的分工,而是在開發期進行代碼存放分離、前后 端開發職責分離,前后端能夠獨立進行開發測試;在運行期進行應用部署分離,前后 端之間通過HTTP請求進行通訊。前后端分離的開發模式與傳統模式相比,能為我們 提升開發效率、增強代碼可維護性,讓我們有規划地打造一個前后端並重的精益開發 團隊,更好地應對越來越復雜多變的Web應用開發需求。