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