最近這幾年,隨著軟硬件技術(shù)的發(fā)展,Web開發(fā)的相關(guān)技術(shù)也在突飛猛進(jìn),跟十年之前甚至五年之前相比,無論是業(yè)務(wù)復(fù)雜度還是技術(shù)選型已經(jīng)完全是兩個(gè)維度。
本文是一篇隨筆,主要闡述一些作者個(gè)人對(duì)web開發(fā)模式的一些認(rèn)知和思考。
在五、六年前,或者更早的時(shí)候,當(dāng)談及Web開發(fā)的時(shí)候,更多的是指代某一種以后端語言為主的技術(shù)棧,比如Java Web,Ruby on Rails,Php等技術(shù)棧。經(jīng)過最近幾年的web開發(fā)相關(guān)技術(shù)的迅速發(fā)展,現(xiàn)在說web開發(fā)可能會(huì)在不同的場(chǎng)景下會(huì)有不同的劃分。
典型的,所謂的Web前端、Web全棧等最近幾年才被逐漸細(xì)分出來的技術(shù)方向,正是在前面這種大環(huán)境下產(chǎn)生的。
言歸正傳,我們說Web開發(fā),那么什么Web開發(fā)?Web開發(fā)的本質(zhì)是什么?
如果在一個(gè)比較高的抽象層面來看這個(gè)問題,Web開發(fā)就是處理客戶端請(qǐng)求及服務(wù)端響應(yīng)這兩件事。
上圖就是一個(gè)非常高的級(jí)別的抽象。實(shí)際的開發(fā)中,還會(huì)有許多方面是需要考慮的。
我們來稍微豐滿一下這個(gè)抽象。
大概2008年左右,一個(gè)web應(yīng)用或者web開發(fā)的標(biāo)準(zhǔn)模型如下圖,
此時(shí),后端主要做的事情是從數(shù)據(jù)庫中拉取數(shù)據(jù),在server端生成html模板,然后將生成的模板發(fā)送到客戶端??蛻舳耸盏侥0搴?,在客戶端注入js和css,生成dom樹,然后渲染成頁面呈現(xiàn)給用戶。
這種模式現(xiàn)在依然在某些web應(yīng)用的開發(fā)中被使用。這種模式現(xiàn)在更多的被稱之為傳統(tǒng)開發(fā)模式,或者前后端混合開發(fā)模式。其主要的一個(gè)特點(diǎn)是,頁面模板由后端吐出,甚至吐出的模板會(huì)帶有樣式和交互。前端僅僅是將模板丟給瀏覽器渲染成dom樹生成頁面而已。有時(shí)候,前端也會(huì)注入一些js代碼為頁面的動(dòng)態(tài)交互提供支持。
這種開發(fā)模式,我本人是實(shí)際經(jīng)歷過的。以前JavaEE、JavaWeb比較火的時(shí)候,經(jīng)常會(huì)寫一個(gè)某某系統(tǒng),比如學(xué)生管理系統(tǒng)、圖書管理系統(tǒng)之類的,在server端通過java來操作JDBC鏈接數(shù)據(jù)庫,拿到需要的數(shù)據(jù),然后將數(shù)據(jù)與jsp組裝起來一起發(fā)送給客戶端,客戶端再交給瀏覽器渲染。后來還經(jīng)歷過php加smarty的開發(fā)模式。其實(shí)這兩種雖然使用的是不同的技術(shù)棧,但是開發(fā)模式的本質(zhì)是一樣的。
但是,這時(shí)候我們會(huì)發(fā)現(xiàn),同一個(gè)開發(fā)者會(huì)扮演好幾種角色,需要寫server端代碼,同時(shí)也需要寫模板層代碼,甚至還會(huì)寫一些js和css代碼。這里需要開發(fā)者在不同角色中切換。但是專注server端的開發(fā)者們往往非常討厭或者說不擅長寫模板、交互和樣式,這時(shí)候又發(fā)展出一種所謂套頁面的開發(fā)模式。所謂套頁面,是指先讓專職的前端開發(fā)切好靜態(tài)頁面,然后丟給后端開發(fā)去模仿然后寫出模板,將需要?jiǎng)討B(tài)變化的地方換成后端模板語法。這種模式已經(jīng)被證明是低效的,而且并沒有合理的應(yīng)用開發(fā)資源。
說到開發(fā)效率,在一個(gè)大體量的團(tuán)隊(duì)協(xié)作中,我們應(yīng)該秉承這樣一種思路,就是讓合適的人去合適的事,分工協(xié)作,流水線作業(yè)肯定是最優(yōu)的方案。
傳統(tǒng)開發(fā)模式下,我們的確有一些痛點(diǎn)需要解決。從而衍生出了這樣一種思路,讓前后端的開發(fā)分離開來,不同工種只負(fù)責(zé)各自的事情,然后遵循某一種協(xié)作約定,達(dá)到高效產(chǎn)出。
上面基本上就是前后端分離的演變歷史。
前后端分離的開發(fā)模式大概如下圖所示,
前后端分離開發(fā)模式下,server端從數(shù)據(jù)庫拿到元數(shù)據(jù),經(jīng)過處理后直接吐出數(shù)據(jù),而不是模板。client端拿數(shù)據(jù)之后,在客戶端端進(jìn)行模板渲染生成頁面呈現(xiàn)給用戶。
相比傳統(tǒng)開發(fā)模式,此時(shí)服務(wù)端不再處理模板層的業(yè)務(wù),而是直接只提供數(shù)據(jù)。職責(zé)更加單一。此時(shí)的服務(wù)端可能會(huì)根據(jù)不同業(yè)務(wù)需求或者架構(gòu)差異,還可能會(huì)直接提供服務(wù)。這里服務(wù)的含義往往指代的是微服務(wù)。甚至在一些非絕對(duì)的前后端分離模式下,服務(wù)端還會(huì)提供模板片段。
顯而易見,此模式下,前端開發(fā)需要做更多的事,而且可能會(huì)隨著業(yè)務(wù)的增長前端邏輯和代碼量會(huì)越來越龐大和復(fù)雜。這又推動(dòng)了各種前端框架的涌現(xiàn),比如Angular這種大而全的框架,比如React這種專注解決某一個(gè)層面業(yè)務(wù)的框架,比如Webpack這種彌補(bǔ)構(gòu)建功能缺失的框架,等等。各種框架本身又會(huì)帶動(dòng)其周邊社區(qū)的發(fā)展,使得整體前端開發(fā)圈子呈現(xiàn)技術(shù)爆炸式的發(fā)展。
除了傳統(tǒng)Web開發(fā)之外,因?yàn)橐苿?dòng)互聯(lián)網(wǎng)的快速發(fā)展,移動(dòng)端開發(fā)、微信開發(fā)、h5開發(fā)等等范疇,也被前端開發(fā)者們照單全收。還有,由于NodeJS平臺(tái)的崛起,前端開發(fā)可能已經(jīng)不僅僅限于瀏覽器端的開發(fā)工作,借助NodeJS平臺(tái),以及Express、Koa等框架,前端開發(fā)者已經(jīng)具備了涉足服務(wù)端開發(fā)的能力。
這里有一篇文章,足以管中窺豹,前端開發(fā)的技術(shù)棧廣度和更新速度。
所以,可以探討的內(nèi)容實(shí)在是非常的多,本文不會(huì)過度發(fā)散,僅僅是探討Web開發(fā)相關(guān)的內(nèi)容。下面會(huì)將重心放在pc端的web開發(fā)模式的探討上,以前后端分離為出發(fā)點(diǎn),闡述本人經(jīng)歷過的兩種開發(fā)模式,以拋磚引玉。
前面有說過,因?yàn)镹odeJS平臺(tái)的活躍,特別是一些成熟的服務(wù)端開發(fā)框架的出現(xiàn),比如express、koa等,讓前端開發(fā)者使用javascript進(jìn)行服務(wù)端程序的開發(fā)成為可能,甚至還可以操作數(shù)據(jù)庫。這也給之前一直在瀏覽器端開發(fā)的前端開發(fā)者們開辟了新的工作場(chǎng)景,如果再掌握一些數(shù)據(jù)庫,http協(xié)議,網(wǎng)絡(luò)安全,web server等方面的知識(shí),那么我個(gè)人感覺前端開發(fā)者完全可以將自己的角色切換成一名后端開發(fā),處理一些通用場(chǎng)景下的后端開發(fā)應(yīng)該是沒有問題的。
顯而易見,這對(duì)傳統(tǒng)的前端開發(fā)者們提出了更高的要求,工作內(nèi)容涉足的領(lǐng)域相比之前而言更加底層,會(huì)更加頻繁的去和真正的后臺(tái)開發(fā)者進(jìn)行溝通,甚至?xí)⑴c一些約定和規(guī)范的制定,這時(shí)候又會(huì)要求我們能夠有一些后端思維,否則你跟別人在溝通事情的時(shí)候都不在頻道上,那怎么可以呢?!
這部分內(nèi)容的標(biāo)題是中間層模式,那么什么是中間層模式呢?我個(gè)人的理解是,以前后端分離為出發(fā)點(diǎn),借助NodeJS平臺(tái),在web后端與傳統(tǒng)前端(UI層)之間增加一層中間層,負(fù)責(zé)處理數(shù)據(jù)、模板、業(yè)務(wù)等內(nèi)容。它是后端與UI層的橋梁。有的人喜歡稱這個(gè)中間層為膠水層。
下面有一張我自己畫的圖,我覺得應(yīng)該可以表達(dá)出我想法中的所謂中間層模式,
通過上面的描述,這種模式下前端開發(fā)們將會(huì)處理三方面的事,
更進(jìn)一步,我們?cè)趯?shí)際項(xiàng)目中,可以將UI層和NodeJS層不必劃分太明確的界限,如下的目錄結(jié)構(gòu),
其中app目錄是NodeJS層代碼,public目錄是UI層代碼,dist是項(xiàng)目構(gòu)建之后的目錄。在項(xiàng)目部署時(shí),只會(huì)針對(duì)dist目錄。
除此之外,這種模式下,我們還有許多可以探索和嘗試的地方,比如
這里我嘗試給一個(gè)中間層模式的解決方案sword-plus。它的定位并不是大而全的一站式解決方案,而是為了更便利的開發(fā)NodeJS層的一系列工具集合以及常用功能的提煉?;?a rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" target="_blank">Koa程序,提供了日志記錄、模板渲染、請(qǐng)求訪問、路由解析、業(yè)務(wù)類抽象等功能。其內(nèi)部的各個(gè)功能組件存在一定程度上的偶合。所以使用sword-plus的前提是,引入NodeJS作為中間層;底層的框架選型為Koa;NodeJS層向上層提供組裝好數(shù)據(jù)的模板。
sword-plus包括以下幾個(gè)部件,Router、Pugger、Connector、Logger、Handler、SwordError。
Router用于解析koa的包裝后的請(qǐng)求。其中有兩個(gè)主要方法,
Pugger主要用于組裝數(shù)據(jù)并渲染Jade/Pug模板。
Connector封裝了NodeJS層->REST層,UI層->NodeJS層的請(qǐng)求操作。內(nèi)部使用了node-fetch。同時(shí)允許在操作請(qǐng)求時(shí),記錄請(qǐng)求日志。它有兩個(gè)方法,
Logger是日志組件,Logger將所有的日志分為如下幾大類(category),
其中第一行其實(shí)是bunyan自帶日志等級(jí)的alias,第二行是根據(jù)不同業(yè)務(wù)場(chǎng)景抽象出來的。
每一條日志都是一個(gè)record抽象,每個(gè)record實(shí)例在category的維度下,還會(huì)有l(wèi)evel的區(qū)分,常用的level有如下幾種info、warn和error。
Handler是業(yè)務(wù)類模型的頂層抽象。所有請(qǐng)求經(jīng)過Router解析之后,都會(huì)通過Handler來派生出具體的業(yè)務(wù)類。在Handler中可以使用內(nèi)部擴(kuò)展或者外部拓展(Handler.inject),來增加所有業(yè)務(wù)類可使用的功能方法。此外,Handler中對(duì)幾個(gè)套件的實(shí)例對(duì)象做了代理,使得在具體的業(yè)務(wù)類中可以使用他們。Handler中提供如下幾個(gè)方法,
SwordError是SwordPlus的Error封裝。用于統(tǒng)一分配error。
目前SwordPlus Error的type有如下幾種,
sword-plus的執(zhí)行流程簡圖大致如下,
具體的使用可以參考sword-plus中的demo文件夾。
這里稍微提一下所謂的完全分離模式,即此模式下的前端開發(fā)和傳統(tǒng)意義上的后端開發(fā)完全隔離開,不會(huì)涉及到中間層的開發(fā)。如下圖,
此時(shí),前端和后端通過ajax請(qǐng)求來交互,后端返回給前端數(shù)據(jù)??蛻舳说乃惺虑?,包括頁面渲染、交互、樣式、路由等等都是由前端自己來管理。此時(shí)前端開發(fā)往往會(huì)引入一個(gè)較為成熟的前端開源框架作為底層選型。這種開發(fā)模式有其獨(dú)特的適用場(chǎng)景,比如單頁應(yīng)用(Single Page Application)、企業(yè)內(nèi)部的某個(gè)管理系統(tǒng)等等。如果前端開發(fā)對(duì)底層選型的框架較為熟悉,往往開發(fā)速度非???,基本上在實(shí)際開發(fā)中遇到的一些問題都可以在框架社區(qū)中找到解決方案。
這種開發(fā)也有其短板的方面,往往隨著需求迭代,前端的代碼量會(huì)越來越多,前端的各種交互和模塊化管理會(huì)越來越重,越來越不好維護(hù)。還有一點(diǎn)就是可供選擇的方案非常多,有時(shí)候你會(huì)不知道到底選擇哪種方案好。
我個(gè)人的看法是,根據(jù)場(chǎng)景和需求來進(jìn)行實(shí)現(xiàn)方案和技術(shù)的選型,不要一味的追求新技術(shù)和潮流。目前前端圈子中流行的幾種主流框架,比如Angular,React,Vue等都會(huì)有其優(yōu)勢(shì)和弱勢(shì)的地方。比如,Angular本身是包羅萬象的框架,一旦熟悉起來開發(fā)速度非常快,但是其入門門檻低深入比較復(fù)雜,而且有一些場(chǎng)景是其先天不適合的。React只關(guān)注View層的處理,提供了一個(gè)非常好的思路告訴我們應(yīng)該如何做View和Data層的交互和更新,但是其現(xiàn)有的數(shù)據(jù)狀態(tài)管理方案比如Redux,我個(gè)人感覺一直都不是太好用。VueJS的作者吸收了市面上眾多框架的優(yōu)勢(shì),個(gè)人感覺它一直都在發(fā)展中,本人并沒有在生產(chǎn)環(huán)境中使用過,不作過多評(píng)價(jià)。
不過話說回來,個(gè)人認(rèn)為前端圈子目前的快速發(fā)展是非常好的,雖然新東西很多,解決同一個(gè)痛點(diǎn)的方案可能會(huì)有很多選擇,但是這并不影響我們?nèi)W(xué)習(xí)他們,去領(lǐng)悟它們的解決問題的思維,甚至去體驗(yàn)一下他們有坑的地方,至于到底要不要再生產(chǎn)環(huán)境使用,那是另外一回事了,所以我個(gè)人并不厭惡前端圈子的當(dāng)下的這種現(xiàn)狀。
這篇文章的主旨意在闡述一些我個(gè)人對(duì)當(dāng)下web開發(fā)模式的認(rèn)知和探索,個(gè)人認(rèn)為文章中的中間層開發(fā)模式是一種萬金油的開發(fā)模式,除了文章中談到的內(nèi)容,我也給出了一些可供繼續(xù)探索下去的點(diǎn),我認(rèn)為中間層開發(fā)模式基本上可以適配任何需求下的web開發(fā)需求。
更多建議: