從傳統(tǒng)網(wǎng)站制作到SPA再到同構(gòu)JavaScript,前端工程師的工作內(nèi)容不斷加重,客戶端邏輯不斷復(fù)雜化。原始的前后端耦合的串行開發(fā)流程已經(jīng)不能滿足Web產(chǎn)品快速的迭代需求,Web開發(fā)者們開始嘗試在開發(fā)、測(cè)試和部署等各個(gè)環(huán)節(jié)尋求更高效的協(xié)作方式。前后端分離似乎就是解決這個(gè)問題的“銀彈”。
顧名思義,所謂前后端分離指的是通過將前端工程師與后端工程師進(jìn)行明確、合理的分工,改善前后端協(xié)作中拖慢開發(fā)進(jìn)度的環(huán)節(jié),提高工作效率。前后端分離的核心是解耦。從開發(fā)、測(cè)試以及部署3個(gè)角度看,前后端分離對(duì)工作效率的提升如下。
·從開發(fā)角度來講,前后端分離的宗旨是實(shí)現(xiàn)并行開發(fā),縮短開發(fā)周期。
·從測(cè)試角度來講,前后端分離令前端工程師和后端工程師更快速、精準(zhǔn)地對(duì)問題進(jìn)行定位。
從部署角度來講,前后端分離將靜態(tài)文件和動(dòng)態(tài)文件分離部署并結(jié)合回滾策略,簡(jiǎn)化了部署流程,增強(qiáng)了應(yīng)用程序的健壯性。
一、原始的前后端開發(fā)模式
首先要說明此處“原始”一詞背后的時(shí)代意義,那是在前端工程師這個(gè)崗位剛剛出現(xiàn)不久,前端工程師普遍地被稱為“切圖仔”或者“美工”的時(shí)代。前后端典型的協(xié)作模式是,前端工程師寫demo,后端工程師寫邏輯和套模板。在這種原始的分工模式下,前端工程師的主要工作是將UI設(shè)計(jì)稿使用HTML和CSS進(jìn)行還原,對(duì)于JavaScript的開發(fā)頂多是實(shí)現(xiàn)一些動(dòng)畫效果,業(yè)務(wù)邏輯基本不涉及。然后,前端工程師將開發(fā)完成的demo交付給后端工程師,后端工程師做的第一件工作是將demo代碼中的HTL和CSS套入服務(wù)器模板引擎中,俗稱“套模板”,而后在此基礎(chǔ)上編寫客戶端的JavaScript業(yè)務(wù)邏輯。
這種協(xié)同工作模式下的開發(fā)效率是非常低下的。請(qǐng)讀者想象一下,如果在進(jìn)行網(wǎng)站的UI測(cè)試時(shí)發(fā)現(xiàn)某個(gè)div的border顏色與設(shè)計(jì)稿不符,或者某個(gè)模塊的顯示完全錯(cuò)亂了,這時(shí)應(yīng)該怎么辦?測(cè)試人員將Bug反饋給開發(fā)團(tuán)隊(duì)后,前端工程師對(duì)Bug進(jìn)行排查,發(fā)現(xiàn)測(cè)試環(huán)境中某個(gè)div的classname寫錯(cuò)了,或者某個(gè)div標(biāo)簽沒有閉合。你可能認(rèn)為這些是后端工程師套模板過程中粗心大意導(dǎo)致的,但是這種問題是無法避免的,人不是機(jī)器,總會(huì)有粗心大意的時(shí)候。如果一個(gè)網(wǎng)站有成百上千個(gè)HTML節(jié)點(diǎn),這種人為過失導(dǎo)致的問題會(huì)被無限放大且非常難以排查。即使我們假設(shè)后端工程師百分之百不會(huì)粗心大意,如果發(fā)現(xiàn)上線后的網(wǎng)站樣式與UI設(shè)計(jì)稿有1像素的偏差,前端工程師修改CSS或者HTML后,仍然需要后端工程師再重復(fù)一次套模板工作,完成后再提交測(cè)試。我們會(huì)發(fā)現(xiàn),這種1像素的Bug修復(fù)需要調(diào)動(dòng)整個(gè)開發(fā)團(tuán)隊(duì)(包括前端工程師和后端工程師)資源。這種模式在前些年非常普遍,而且很不幸的是,至今國(guó)內(nèi)仍然有相當(dāng)一部分團(tuán)隊(duì)使用這種原始的協(xié)作模式。
這種原始的前后端協(xié)作模式之所以在前些年比較普遍,一是因?yàn)楫?dāng)時(shí)客戶端的邏輯并不十分復(fù)雜,JavaScript邏輯交給后端工程師就可以了,不需要專業(yè)的前端工程師。事實(shí)上,當(dāng)時(shí)有相當(dāng)一部分寫demo的工作是交給UI設(shè)計(jì)師負(fù)責(zé)的,當(dāng)然需要一些專業(yè)工具輔助,比如微軟的DreamWeaver;二是因?yàn)楫?dāng)時(shí)網(wǎng)站的迭代需求并不像如今這么快,沒有頻繁的更新也就不需要特別高效的生產(chǎn)流水線。但是在如今的市場(chǎng)環(huán)境下,一方面Web應(yīng)用的迭代效率是爭(zhēng)取用戶的必要手段之一;另一方面,前端技術(shù)的快速發(fā)展已經(jīng)超越了后端工程師的能力范疇,必須由專職的前端工程師負(fù)責(zé)。在這種環(huán)境下,原始的前后端開發(fā)模式的弊端被進(jìn)一步地放大了,前后端分離便應(yīng)時(shí)而生了。
二、前后端分離的基本模式
合理的分工是前后端分離的第一步,也是后續(xù)各種優(yōu)化方案的基礎(chǔ)。團(tuán)隊(duì)人員按職能分為前端工程師和后端工程師,按照前面總結(jié)出的前端工程師的定位,前端工程師負(fù)責(zé)的內(nèi)容包括以下幾方面。
·CSS以及相關(guān)的圖片等媒體資源。
·JavaScript邏輯。
·HIML文檔,包括產(chǎn)出HTML的源文件,比如HIML模板。
對(duì)于前端工程師來說,后端工程師的唯一產(chǎn)出就是數(shù)據(jù),包括用于服務(wù)器渲染HTML模板的初始數(shù)據(jù)和客戶端異步請(qǐng)求接口返回的數(shù)據(jù)。
明確了各自的分工后,我們分別從開發(fā)、測(cè)試和部署3個(gè)方面分析前后端分離要解決哪些問題。
1.開發(fā)
開發(fā)階段前后端分離要解決的問題可以按照資源類型分為兩種:靜態(tài)資源的處理和動(dòng)態(tài)資源的處理。
靜態(tài)資源指的是JavaScript、CSS、圖片等,這類資源在瀏覽器的呈現(xiàn)方式是靜態(tài)的,不需要服務(wù)器做任何處理。動(dòng)態(tài)資源指的是HTL模板,除非你的項(xiàng)目不需要任何服務(wù)器端渲染的SPA,否則我們?nèi)匀徊豢杀苊獾匾幚砬昂蠖俗铍y解耦的HTL模板。
靜態(tài)資源的處理相對(duì)簡(jiǎn)單,因?yàn)檫@類文件不依賴任何服務(wù)器環(huán)境,只要最終在瀏覽器里解析即可。HTML模板的處理方案可以按照項(xiàng)目類型分為以下幾種。
(1)SPA項(xiàng)目。這類項(xiàng)目中不存在HTL模板的概念,所有的HTML實(shí)體內(nèi)容均由JavaScript在瀏覽器下生成。所以SPA項(xiàng)目中可以將html文件作為靜態(tài)文件處理。
(2)HTML模板由服務(wù)器端部署的項(xiàng)目。這類項(xiàng)目最終的HTL模板需要與服務(wù)器端代碼一同打包部署。由于靜態(tài)文件必須由HTML引入,為了避免“套模板”,開發(fā)階段前端工程師直接編寫HTML模板更有利于快速開發(fā)和問題定位。
(3)大前端項(xiàng)目。這類項(xiàng)目中前端工程師負(fù)責(zé)與客戶端相關(guān)的所有文件,包括靜態(tài)文件與HIML模板,這是最理想的模式??梢钥闯霾徽撌荢PA還是大前端,開發(fā)階段的前后端分離都比較容易實(shí)施。但我們不得不面對(duì)的一個(gè)現(xiàn)實(shí)是,目前國(guó)內(nèi)的Web產(chǎn)品絕大多數(shù)是第二種項(xiàng)目類型。這也是最難以實(shí)現(xiàn)完全前后端分離的項(xiàng)目。
之所以稱為“大前端”而不是“全棧工程師”是因?yàn)榇笄岸送ǔ2唤佑|數(shù)據(jù)庫操作。大前端負(fù)責(zé)的并不是真正的Web服務(wù)層,而是中間層。中間層的作用主要解決的就是HTL的渲染,這也是為了實(shí)現(xiàn)前后端分離而探索出的一個(gè)模式。
對(duì)于HTTL模板由服務(wù)器端部署的項(xiàng)目,前后端分離要解決3個(gè)問題。
(1)HTML模板引擎的支持。
(2)HTML模板的初始數(shù)據(jù)。
(3)各種異步數(shù)據(jù)接口的數(shù)據(jù)。
HTML模板引擎種類繁多,并且根據(jù)服務(wù)器端編程語言的不同,部署難度也不盡相同。易部署的如PHP、Node.js、Python等,稍難部署的如Java、.NET等。目前的市場(chǎng)情況較之前有了比較明顯的改善,Node.js的不斷改進(jìn)已經(jīng)令很多初創(chuàng)團(tuán)隊(duì)選擇Node.js作為Web服務(wù)的編程語言。并且成熟的團(tuán)隊(duì)通常都有中間層,Java承載著大后端數(shù)據(jù)服務(wù),中間層使用易部署的編程語言,比如PHP、Node.js和Python。
HTL模板的初始數(shù)據(jù)和異步接口的數(shù)據(jù)都可以用Mock服務(wù)解決。前后端開發(fā)人員在編寫代碼之前約定好接口的請(qǐng)求規(guī)范和數(shù)據(jù)結(jié)構(gòu)。開發(fā)期間,前端工程師按照規(guī)范使用Mock服務(wù)提供的模擬數(shù)據(jù)進(jìn)行開發(fā)。Mock服務(wù)處理HTML模板的初始數(shù)據(jù)和異步接口數(shù)據(jù)稍有不同,HTML模板數(shù)據(jù)需要在服務(wù)器端渲染使用,在MWC架構(gòu)模型中,這類數(shù)據(jù)通常由Controller提供給HTL模板引擎。在非大前端模式下,前端工程師如果不想花費(fèi)時(shí)間與精力編寫模擬Controller代碼,可以在構(gòu)建工具上下點(diǎn)功夫。在渲染HTML模板時(shí)注入約定格式的數(shù)據(jù)即可,本書將在第4章詳細(xì)講解具體的實(shí)現(xiàn)方案。
2.測(cè)試
測(cè)試分為兩個(gè)階段,第一個(gè)階段是前后端工程師的單元測(cè)試,這個(gè)階段前后端工程師的測(cè)試是獨(dú)立的,各自的測(cè)試流程和結(jié)果不會(huì)影響對(duì)方;第二個(gè)階段是集成測(cè)試,這個(gè)階段前后端的代碼進(jìn)行整合,在測(cè)試環(huán)境下由專業(yè)的測(cè)試工程師進(jìn)行測(cè)試用例遍歷。
前后端分離首先要解決的是集成測(cè)試階段的問題及時(shí)定位,解決方案并不是通過技術(shù)或工具,而是通過明確責(zé)任承擔(dān)角色。測(cè)試工程師等同于內(nèi)測(cè)用戶,站在用戶的角度上對(duì)產(chǎn)品進(jìn)行使用和評(píng)估,他們反饋的問題就等同于是用戶的反饋。既然是用戶的反饋那么直接責(zé)任人就應(yīng)該是前端工程師。前端工程師負(fù)責(zé)所有與用戶直接接觸的功能和邏輯,所以有責(zé)任在出現(xiàn)問題時(shí)站在第一線。后端工程師的產(chǎn)出并不與用戶直接接觸,前端工程師更容易定位用戶層面的問題。理想情況下,服務(wù)器端單元測(cè)試覆蓋率達(dá)標(biāo)并且測(cè)試通過后,接口是不應(yīng)該存在邏輯性錯(cuò)誤的。如果客戶端出現(xiàn)因數(shù)據(jù)引起的問題,通常是因?yàn)榭蛻舳说腏avaScript邏輯存在問題比如一些side effect(臨界問題)沒有處理好。即使服務(wù)器端的單元測(cè)試沒有達(dá)到理想情況,前端工程師通過調(diào)試工具也更容易發(fā)現(xiàn)問題的癥結(jié)。
前后端分離不僅僅是通過技術(shù)手段解決問題,技術(shù)和工具只是輔助,其本質(zhì)是分工和角色的細(xì)分。這恰恰是目前很多團(tuán)隊(duì)在進(jìn)行前后端分離時(shí)容易忽略的問題。
除集成測(cè)試階段外,前后端分離還必須兼顧產(chǎn)品在生產(chǎn)環(huán)境下的質(zhì)量保障問題。目的仍然是對(duì)出現(xiàn)問題的及時(shí)預(yù)警和快速修復(fù)。這方面的通常做法如下:
制定客戶端監(jiān)控系統(tǒng),收集客戶端問題并及時(shí)通知開發(fā)人員。
大多數(shù)團(tuán)隊(duì)并未將生產(chǎn)環(huán)境的客戶端質(zhì)量保障作為前后端分離的一部分。服務(wù)器端通常具備監(jiān)控、預(yù)警以及應(yīng)急策略,盡可能保證服務(wù)器問題的及時(shí)處理。同理,客戶端也應(yīng)該具備監(jiān)控機(jī)制,并且由前端工程師負(fù)責(zé)。
3.部署
前后端分離在部署階段要解決的問題是靜態(tài)資源和動(dòng)態(tài)資源的分離部署。
與開發(fā)階段類似,不同的項(xiàng)目類型需要制定不同的部署方案。在3種項(xiàng)目類型中,大前端模式下的部署方案是最簡(jiǎn)單的,因?yàn)榍岸斯こ處熌軌蛘瓶厮佑|的所有資源。具體部署方案如下。
·將JS、CSS、圖片等靜態(tài)資源部署到靜態(tài)文件服務(wù)器。
·HTL模板文件與中間層的Node.js代碼一同部署到Web服務(wù)器。
SPA項(xiàng)目的部署方案稍微復(fù)雜一些,由于SPA中的html文件不需要在服務(wù)器端渲染,因此其理論上可以與其他靜態(tài)資源一同部署到靜態(tài)文件服務(wù)器。但是需要注意的一個(gè)問題是,不能令瀏覽器將html文件強(qiáng)制緩存到本地。如果用戶之前訪問過此頁面,html文件被瀏覽器強(qiáng)制緩存到本地,那么即使開發(fā)人員更新了html文件,也會(huì)由于瀏覽器的緩存策略而無法獲取最新版本的資源。除非用戶手動(dòng)清除瀏覽器緩存,而這顯然是不可行的。解決這個(gè)問題的辦法有兩種,分別如下。
(1)分別為html文件與其他靜態(tài)資源設(shè)置不同的緩存策略。html文件可以使用協(xié)商緩存策略(瀏覽器HTTP請(qǐng)求返回狀態(tài)碼304),其他靜態(tài)資源使用強(qiáng)緩存策略(瀏覽器HTTP請(qǐng)求返回狀態(tài)碼“200(from cache)”。關(guān)于這兩種緩存策略的詳細(xì)內(nèi)容本書會(huì)在第3章介紹。
(2)使用一刀切的方案,所有靜態(tài)資源均使用協(xié)商緩存策略。
第一種方案不論是從客戶端性能、用戶體驗(yàn),還是從服務(wù)器端壓力的角度來講都優(yōu)于第二種。具體實(shí)施也不是很麻煩,Apache、Nginx等專業(yè)服務(wù)器軟件都可以針對(duì)文件擴(kuò)展類型設(shè)置不同的緩存策略。
最麻煩的是第二種項(xiàng)目,也就是HTML模板由服務(wù)器端部署,并且前端工程師不負(fù)責(zé)中間層或者服務(wù)器端開發(fā)的項(xiàng)目。這類項(xiàng)目通常的部署方案如下。
·靜態(tài)資源部署到靜態(tài)文件服務(wù)器。
·HTL模板文件編寫完成之后由前端工程師通過SVN、Git等版本管理工具同步到代碼倉庫,后端工程師拉取最新代碼后,將模板文件與服務(wù)器端邏輯代碼一同部署。
靜態(tài)資源和動(dòng)態(tài)資源分離部署的優(yōu)點(diǎn)是:在集成測(cè)試階段,對(duì)于只涉及一方(前端或者后端)的Bug,相關(guān)負(fù)責(zé)人修改代碼后獨(dú)立進(jìn)行部署即可,不需要另一方再行部署。比如CSS樣式出現(xiàn)問題,前端工程師修改css文件后部署到靜態(tài)文件服務(wù)器,不需要后端工程師再部署一次服務(wù)器端文件即可在瀏覽器刷新后獲取修復(fù)后的文件。當(dāng)然,這個(gè)優(yōu)點(diǎn)只是針對(duì)測(cè)試階段,因?yàn)榇蟛糠止竟y(cè)試使用的靜態(tài)文件服務(wù)器是不設(shè)置客戶端緩存的,這樣可以保證測(cè)試環(huán)境下每次訪問網(wǎng)站都能拿到最新的資源。但是在生產(chǎn)環(huán)境下必須使用瀏覽器緩存,所以修復(fù)生產(chǎn)環(huán)境的問題必須按照上述部署策略進(jìn)行重新部署。本書第5章將介紹具體的部署方案。
三、前后端分離與前端工程化
前后端分離策略是制定前端工程化解決方案的指導(dǎo)方針之一;前端工程化的最終目的之一便是實(shí)現(xiàn)更合理、更便利的前后端分離開發(fā)環(huán)境。兩者相互依賴、緊密耦合在一起。如果將前后端分離策略比喻成建筑設(shè)計(jì)圖,那么前端工程化方案就是按照這張?jiān)O(shè)計(jì)圖進(jìn)行具體建設(shè)的。在前端工程化這棟建筑平臺(tái)上,前端開發(fā)人員和服務(wù)器端開發(fā)人員可以更順暢、更高效地進(jìn)行開發(fā)工作。
今天的網(wǎng)頁制作分享就到這了,如果您喜歡這篇文章,您可以分享給你的朋友!深圳網(wǎng)站建設(shè)-博納網(wǎng)絡(luò)編輯整理。