世界是平的嗎?——從不同角度看前端
在遠古的時候,人們對世界的認知有限,以為天圓地方,世界是平的。后來,隨著科技進步,大家都知道了地球的形狀,它不但不平,還有山川河流,沙漠海洋。
這很大程度上說明了人所處的環境對認知帶來的影響,我們看待一件事物,從不同的視角去看,所得到的結論未必是相同的。
前后端協作的研發模式
上個月有一天很奇妙,早上有個之前部門的同事跟我探討研發模式,下午有個之前同事跟我吐槽前后端溝通成本高,晚上部門群里又有人提到視圖跟服務的關系,這么多巧合,值得在這個事情上寫點東西。
回頭看看這幾年,前端領域在搞的一些東西,除去具體的框架和組件庫,大致有這么些:
- 工程體系:構建、發布、持續集成、容器管理
- NodeJS實現的框架、中間件、服務
- 圍繞前后端協作展開的一系列探索:BaaS、BFF、函數計算、GraphQL等
- 跨端實踐
這里面,有很大一部分話題是跟廣義的“前后端分離”有關的。站在今天這個時間回頭看,看得到每個方向的進展,人們逐步習慣了前端有類型、有構建、有包管理、有測試、有持續集成等等,前端開發逐步成為了相對嚴謹的軟件生產活動。
另外一方面,當我們把目光投向整個系統的時候,我們也可能發現研發流程的一些狀況?,F在,一個典型的系統,它的開發過程可能是這樣的:
- 前端獨立系統
- 后端獨立系統
- 中間有類似 swagger 的接口約定機制
前端有一套東西,完整的組件化、構建、發布、依賴管理,后端也有一套,但是,兩者的結合往往是很松散的,整個鏈路很長,在流程上會有很不協調的感覺。
形成這個問題的原因是整個研發過程兩極分化,斷裂得很厲害,前后端的唯一橋梁是接口,并且,一般來說,當一端產生了變更之后,很難有一種自動同步機制去影響另一端,通常只能去掃描發現這些不一致的地方,并且手工做調整。

整個系統的研發流程好比細胞的增殖過程,拉伸成了兩塊,中間的維系很脆弱。
從架構治理角度看,“兩頭大”的情況是需要去控制的,只有主從結構的形態,在流程上才是簡單的。對這么一個問題,業界存在不同的探索途徑:
- 前端主導的流程
- 前后端合一的研發模式
- 后端主導的流程
前端主導的流程
前端主導的流程是怎樣的呢?
這個流程的要點是讓后端退化為配置,借助 BaaS,FaaS 這樣的基礎架構,舍棄后端的構建與發布環節,工程上就會成為這樣的形態:

這樣,后端成為了一種流程無感的環節,前端是整個項目的集成方,后端成為了一種配置化的東西,成為了前端體系下的附屬。這種模式是否能行得通,最大的先決條件就是后端接口是否穩定。在互聯網企業中,尤其是領域模型關聯關系較少的情況下,有不少系統在往這個方向走。
- 輕量業務:完全 BaaS
- 較重的業務:通過 Faas 調用微服務
前后端融合的模式
另外,業界也存在一些探索,希望把前后端的開發過程融合。我們所要解決的問題一直都是變更的同步,那么,如果一個項目的前后端都位于一個工程中,天然對同步也是有利的。

這種模式下,實際上是通過兩者合一的方式,縮短了前后端研發過程之間的距離和溝通成本,在此基礎上,還可以有另外一些手段作優化,比如:
- 根據后端的服務生成前端的調用接口,并且附帶 TypeScript 類型描述
- 根據后端的單元測試生成前端的 mock 數據
前后端合一的工程中,最大優勢就是后端接口的變更一定會自動傳導到前端,服務接口字段變更會導致:
- 前端類型校驗出錯
- 前端的單元測試出錯
并且,由于二者合并在一個項目中,改了一邊忘記改另一邊的情況也更不容易發生,兩者的發布也是在同一個流程中。
這種模式普適性相對好,但是對人員全棧技能的需求是要稍高的。
后端主導的流程
后端主導的流程又是怎樣的呢?
這個流程是反過來,盡可能地把視圖弱化,讓它成為后端模型的附屬物。在很長的時間里,這種形態一直是主流,只是可能具體形式上歷經了一些演變。
后端主導的流程推行到極致,工程上就會成為這樣的形態:

在這種路徑下,視圖成為了領域模型的附屬物,當領域模型產生變動的時候,視圖自然跟著變動,即使是視圖之間的聯動關系,也是經由領域模型之間的關系控制的。
這樣,前端成為了一種流程無感的環節,后端是整個項目的集成方,前端成為了一種配置化的東西。這條路徑的先決條件是前端的模式相對固定,可窮舉,不會存在太多的個性化交互。通常,會有一些企業軟件的研發過程采用這種模式。這種模式對人的需求是領域建模能力較強。
組件化
研發流程也會導致實施過程中的一些細節差異,比較典型的就是組件化。
組件化是一個很久遠的名詞了,自從工業革命開始,標準化的可替換部件逐步成為了生產效率的基石。在前端領域,這個詞最近也在越來越多地被提到。然而,對這個詞如何理解,不同的人有不同看法。
組件化的實施路徑是需要隨著技術方案的不同而調整的。剛才我們提到了三種研發模式,組件化實施方案也會有不同的模式。
- 前端不分層的組件化體系
- 前端分層的組件化體系
- 端到端組件化體系
前端不分層的組件化體系
這個體系是當前前端最熟悉的路徑了,在實現者眼里,后端退化為接口,不關心數據之間的關系。

前端分層的組件化體系
另外存在一種實踐,在前端又引入分層,把真正的視圖和邏輯、數據等等隔離,這個時候,視圖部分實際上就可以變得非常薄,整個視圖部分的組件化,實際上類似于模板化。

端到端的組件化體系
如果考慮到實施的原則盡量簡單,端到端組件是最容易理解,集成難度最低的一種形態。
在此模式下,單個組件應當包含視圖到服務端模型的整個鏈路。組件只跟某個具體的領域模型交互,并不關心其他組件的存在。單個或者多個組件,都能夠直接運行。頁面成為一種通用的容器,把它們集成起來。

舉例來說,一個人員列表與詳情的頁面,如果實現為兩個組件,其功能分別如下:
- 列表組件
- 綁定了某個條件的人員列表查詢服務
- 詳情組件
- 綁定了某個具體的人員
這兩個組件應當是互相獨立的,在這種情況下頁面對它們的集成,包括兩者之間的聯動關系,都是在領域模型(后端)上定義的,然后借助特定的機制,自動就形成了聯動關系。
從實現角度,這種組件內部也可能接近于其他形態的組件實現方式,比如,組件內部可以有分層,當某組件被注冊的時候,它所屬的各層是分別注冊的。
需要注意的是,以上三種實踐并非直接對應于第一部分我們提到的三種模式,它們是存在并存關系的,可以根據業務場景去適當進行混合。
小結
不考慮實際情況的技術選型是非常可怕的,并不存在通吃一切的技術方案,每種方案都有它的邊界。在實踐過程中,可以問問自己,我們正在做的這個系統:
- 前端跟后端,哪塊更模式化?
- 與其他系統的集成方式是怎樣的?
- 視圖變更與復用程度如何?
- 人員的技能狀況如何?
- 視圖是“寫”出來的,還是“配置”出來的?
對這些問題的不同回答,都會影響到具體實施路徑的選擇。
幾年前,左耳朵耗子說了一句話,被很多人圍攻:“CSS不就是配置文件么?”從前端角度看,這句話簡直大逆不道。但是,在某些場景下,當我們把視野放在全局,到整個系統層面,CSS確實就可以被認為是一種配置文件。不但如此,在有些場景下,連視圖的大部分都能算是配置文件了。
有的時候,我們也會看到一些探索,比如說,嘗試用可視化的方式去配置視圖層,在這種情況下,視圖確實就是由:
- “寫”出來的基礎組件
- “拼”出來的大塊模板
這兩類部分所組成的,這也是我個人在很多情況下很傾向于“模板型”視圖層框架的原因。
我們繞了很大一圈,離題萬里,那么,世界是平的嗎?
可以試試閉著眼睛去摸一下立體的地球儀,感覺是怎樣的?但實際上這是一種錯覺,因為地球儀對比例進行了夸張,以青藏高原的海拔,相對地球半徑而言,其高度差簡直可以忽略不計。所以,宏觀角度看,世界確實就是平的。
橫看成嶺側成峰,遠近高低各不同。不識廬山真面目,只緣身在此山中。
——蘇軾
后記:本文是2019年1月19日在網易前端技術大會上的分享。整篇文章想要解決的問題是給出一些建議:前端技術選型應當結合業務場景,社區方案只是自己的工具,技術人員不應當變成工具的奴隸。在不合適的場景下,即使是很著名、流行的工具,也應當果斷舍棄。
分享過程中,我提到自己給自己打的標簽是缺乏情懷的工業黨,所謂工業黨,在我看來,有另外一個名詞可以對等,那就是生產力至上。一個生產力至上者的態度是這樣的:竭盡全力尋找出限制生產力發展的因素,找到最適合的生產方式:
- 如果生產工具(技術框架)是瓶頸,那就改造生產工具;
- 如果研發流程是瓶頸,那就重塑研發流程;
- 如果人是瓶頸,那就改變人。