前后端分離是現在互聯網項目開發的業界標准使用方式,我們來看看它的發展。
前后端未分離時代(各種耦合)
這個時代可以叫做MVC時代,因為主要是使用MVC框架。
大致就是,所有的客戶端請求都被發送給作為控制器的Servlet,它接收請求,並根據請求信息將它們分發給適當的JSP來響應。同時,Servlet還根據JSP的需求生成JavaBeans的實例並輸出給JSP環境。JSP可以通過直接調用方法或使用UseBean的自定義標簽得到JavaBeans中的數據。需要說明的是,這個View還可以采用Velocity、Freemarker等模板引擎。使用了這些模板引擎,可以使得開發過程中的人員分工更加明確,還能提高開發效率。
在這個時期,首先是有以下的開發方式。
這種方式已經逐漸淘汰。主要原因有兩點:
1.前端在開發過程中嚴重依賴后端,在后端沒有完成的情況下,前端根本無法干活。
2.由於趨勢問題,會JSP、懂Velocity和曉Freemarker等模板引擎的前端越來越少。
因此進化出了另一種開發方式,這種方式現在很多小型傳統軟件公司還在使用。
但是這種開發方式和它前身的開發方式有着同樣的缺點:
1.前端無法單獨調試,開發效率低。
2.前端不可避免會遇到后台代碼。比如說JSP中的EL表達式和JSTL標簽,難為前端。這種方式的耦合性太強,就算用了Freemarker等模板引擎,前端也不可避免地要去重新學習該模板引擎的語法,無謂增加了前端的學習成本。
3.JSP本身局限所導致的性能問題。一是第一次請求JSP,必須要在WEB服務器中編譯成Servlet,造成第一次運行會比較緩慢的結果;二是每次請求JSP都要訪問Servlet再用輸出流輸出HTML頁面,效率比直接使用HTML低下;三是JSP是同步加載的方式,如果頁面中有很多內容,頁面響應會很慢。
前后端半分離時代
走過了前后端未分離的時代,來到了前后端半分離的時代。在這個時代,前端負責開發頁面,通過接口(AJAX)獲取數據,采用DOM操作對頁面進行數據綁定,最終是由前端把頁面渲染出來,這也就是AJAX與SPA應用(單頁應用)結合的方式,其結構圖如下:
1.瀏覽器請求,CDN返回HTML頁面。
2.HTML中的JS代碼以AJAX的方式請求后台的RESTFUL API接口。
3.接口響應並返回JSON數據,頁面解析JSON數據后通過DOM操作渲染頁面。
這里后端提供的都是以JSON為數據格式的API接口供Native端使用,同樣提供給WEB的也是JSON數據格式的API接口,那么就意味着WEB的工作流程是:
1.打開WEB瀏覽器,加載基本資源,如CSS、JS和圖片等。
2.使用JS發起一個AJAX請求到服務端請求數據,同時展示LOADING(加載中)。
3.得到JSON格式的數據后再根據邏輯選擇模板渲染出DOM字符串。
4.將DOM字符串插入頁面中WEB VIEW渲染出DOM結構。
這些步驟都由用戶所使用的設備中逐步執行,也就是說用戶的設備性能與APP的運行速度緊密聯系,換句話說,如果用戶的設備很低端,那么APP打開頁面的速度就會很慢,極度影響用戶體驗。
為什么說是半分離的呢,因為不是所有頁面都是單頁面應用。在多頁面應用的情況下,前端因為沒有掌握Controller層,前端需要和后端討論頁面是要同步輸出還是異步JSON渲染。而且即使在這個時期,通常也是一個工程師搞定前后端所有的工作。因此在這個階段只能算半分離。
這個時代比起上一個時代還是有進步的,首先前端不會嵌入任何后台代碼,前端專注於HTML、CSS、JS的開發,不依賴於后端。自己還能夠模擬JSON數據來渲染頁面,發現BUG也能迅速定位出是誰的問題。
然而在這種架構下還是存在明顯的弊端的,最明顯的有如下幾點:
1.JS存在大量冗余,在業務復雜的情況下,頁面的渲染部分的代碼非常復雜。
2.在JSON返回的數據量比較大的情況下,渲染非常緩慢,會出現頁面卡頓的情況。
3.SEO(Serach Engine Optimization,搜索引擎優化)非常不方便。由於國內的搜索引擎的爬蟲無法爬下JS異步渲染的數據,導致這樣的頁面SEO會存在一定的問題。
4.資源消耗嚴重,在業務復雜的情況下,一個頁面可能要發起多次HTTP請求才能將頁面渲染完畢。可能有人不服,覺得PC端建立多次HTTP請求也沒啥,但是移動端建立一次HTTP請求的消耗十分巨大。
真是因為如上的缺點,我們在亟需真正的前后端分離架構。
前后端分離時代
經過了前后端未分離、前后端半分離的時代后,終於迎來了前后端分離時代。在這個時代,前端的范圍被擴展,Controller層也被認為是屬於前端的一部分。前端負責View和Controller層,后端只負責Model層和Service層。
可是后端開發人員對前端的HTML結構不熟悉,前端開發人員也不懂后台代碼啊,Controller層要怎么實現呢?這時NodeJS橫空出世了,NodeJS適合運用在高並發、I/O密集、少量業務邏輯的場景。最重要的一點是,前端不用再學一門其它語言了,美滋滋。
可以把NodeJS當成跟前端交互的API。總的來說,NodeJS的作用在MVC中相當於C(Controller,控制器)。NodeJS路由的實現邏輯是把前端靜態頁面代碼當成字符串發送到客戶端(例如瀏覽器),簡單理解可以理解為路由是提供給客戶端的一組API接口,只不過返回的數據是頁面代碼的字符串而已。
用NodeJS來作為橋梁架構服務端API輸出的JSON能帶來優異性能。后端處於性能和別的原因,提供的接口所返回的數據格式也許不太適合前端直接使用,前端所需的排序功能、篩選功能以及到了視圖層的頁面展現,也許都需要對接口所提供的數據進行二次處理。這些處理雖然是可以放在前端來執行,但如果數據量一大,便會浪費瀏覽器性能,更會降低頁面渲染速度,影響用戶體驗。因而如今增加NodeJS中間層是一種良好的解決方案。
增加了NodeJS中間層之后,瀏覽器(Webview)便不再直接請求服務端的API,而是瀏覽器先去請求服務端的NodeJS,由NodeJS對服務端的API發起HTTP請求,NodeJS收到服務端的API響應返回的JSON后就去渲染HTML頁面,然后NodeJS直接將HTML頁面flush到瀏覽器。這樣,瀏覽器得到的就是普通的HTML頁面,不再用發AJAX去請求服務器之后再在瀏覽器進行頁面渲染了。
增加NodeJS中間層主要有以下優點:
1.適配性提升。我們在開發過程中,經常會給PC端、Mobile、App端各自研發一套前端。其實對於這三端來說,大部分業務邏輯是一樣的,唯一的區別就是交互展現邏輯的不同。如果Controller層在后端手里,后端為了這些不同端頁面展現邏輯,自己維護這些Controller,模板無法重用,徒增與前端溝通成本。如果增加了NodeJS層,每種前端的界面展示邏輯由NodeJS層自己維護。產品經理在中途如果想要改動界面,可以由前端自己維護,無需后端操心。前后端各司其職,后端專注於自己的業務邏輯開發,前端專注於產品效果開發。
2.響應速度提升。有的時候會遇到后端返回給前端得數據太簡單了,需要前端對這些數據進行邏輯處理。那么在數據量比較小得時候,對其做運算分組等操作,並無影響。但是當數據量大的時候,會有明顯的卡頓效果。這時候,NodeJS中間層其實可以將很多這樣的代碼放入NodeJS層處理,也可以替后端分擔一些簡單的邏輯、又可以用模板引擎自己掌握前台的輸出。這樣做,靈活度、響應度都有較大的提升。
3.性能得到提升。大家應該都知道單一職責原則,從該角度來看,我們請求一個頁面,可能要響應很多個后端接口,請求變多了,自然速度就變慢了,這種現象在Mobile端更加嚴重。采用NodeJS作為中間層,將頁面所需要的多個后端數據直接在內網階段就拼裝好,再統一返回給前端,會得到更好的性能。
4.異步與模板統一。淘寶首頁就是由幾十個HTML片段(每個片段一個文件)拼裝成的。之前PHP同步加載這幾十個片段,一定是串行的,換成NodeJS之后就可以實現異步加載,讀文件可以並行,一旦這些片段中也包含業務邏輯,異步的優勢就很明顯了,真正做到哪個文件先渲染完就先輸出顯示。前端機的文件系統越復雜,頁面的組成片段越多,這種異步的提速效果就越明顯。前后端模板統一在無線領域很有用,PC頁面和WIFI場景下的頁面適合前端渲染(后端數據通過AJAX返回到前端),2G/3G弱網絡環境則適合后端渲染(數據隨着頁面一起返回給前端),所以同樣的模板,在不同的條件下走不同的渲染渠道,模板只需要一次開發。
前后端分離的缺點
前后端分離有優點,自然也會有缺點,因為凡事都有兩面性的。
1.人員問題。宣傳這種架構的公司一般都是很高級別的公司,一般的中小型公司沒有這樣的前端資源來支撐這樣的架構。如果強推前后端分離的架構可能會導致很多問題 ,比如后端被逼着去學VueJS,NodeJS這些,白白增加后端的負擔,甚至會造成后端開發紛紛離職的情況。
2.產品迭代周期的問題。中小型的軟件公司一般需要一個比較快的軟件迭代周期。采用前后端分離架構的話,增加了一個接口指定流程和前后端聯調流程。從本質上來說放慢了迭代的周期。
3.前端需要學習業務知識。本來前端只需要掌管視覺交互的部分。現在因為Controller層也歸前端管了,前端必須對公司的業務流程有深入的了解,才能准確地寫出顯示邏輯。不過這樣會讓后端覺得前端奪權,前端在混KPI。前端雖然必須要去學無聊的業務,但是有得必有失,前端也因此能夠站穩腳跟。也許正是因為前后端分離架構的出現,前端可以朝着架構師進軍。
總結
前后端分離雖然很熱門,但是也是要謹慎選擇使用的,特別是一些中小型的軟件公司要慎用。一定要弄清楚自己的定位,不要妄自菲薄,技術最終是為業務服務的,能完美實現業務、並使用最低的開發成本的才是好技術。
"每個人都在努力,每個人都很忙。"