本文首發於歐雷流。由於我會時不時對文章進行補充、修正和潤色,為了保證所看到的是最新版本,請閱讀原文。
從事前端開發的你,不知有沒有被問過:「前端有架構嗎?」
問你的人的身份,可能是你的 boss 或上司,可能是後端同事,也可能是前端同行;問你的人的目的,可能是刁難,可能是嘲諷,也可能是請教。
前端開發
眾所周知,做前端開發所依賴的核心技術就是 HTML、CSS 和 JS,就像好基友一樣形影不離,我們將它們仨親切地並稱為「三劍客」。
經過這二十多年,尤其是在 V8 引擎及 Node.js 出現之後,以「三劍客」為基礎的衍生技術如雨後春筍般大量出現,前端及其關聯社群與前端工程師這個職業得到了空前的蓬勃發展,甚至讓很多人覺得一個前端工程師不僅僅可以做 web 前端開發,還可以寫後端,替代客戶端工程師——前端技術一統天下!
工作內容
除了做網頁,前端技術還能應用於命令列工具、客戶端應用、服務端應用、聊天機器人、爬蟲、IoT 等場景。只要腦洞足夠大,就不怕場景不夠多。
然而,絕大部分的前端工程師在工作中都會接觸到這些嗎?
試想一下,自己的工作歷程是不是這樣的——
在一家 150 人規模以下的創業公司,可能業務還在摸索期,需要不斷地快速試錯以找到可以鉚足勁兒去發力的點。這時前端團隊也沒幾個人,可能就三五個吧,並且 leader 不是什麼大牛,也沒有一套方法論作為團隊建設的指導,也許你是這個團隊裡實力最強的。
這個時期所需要的就是能夠快速迭代產出成果,然後去驗證是否有效。根本不會給你時間去思考、規劃前端團隊的發展方向與基礎設施建設。如果特意花費時間去做這些,沒準兒公司會認為你「不務正業」,到時 KPI 打個不及格。
經歷一段時間的焦頭爛額,在此期間工程目錄、程式碼提交很可能都很隨意,並且沒有 code review。有空閒下來回頭一看,程式碼一坨一坨跟那個什麼似的,實現與「優雅」這個詞絕緣。
隨著業務的快速發展,專案、應用越來越多,團隊人數也越來越多,然而規範約定、基礎設施依然幾乎沒有。在業務線做開發的前端,也不太會想著整個團隊的工具統一,自己怎麼爽就怎麼來。最終導致一個團隊用了多種檢視層庫、多個元件庫,給收斂技術棧帶來很大阻礙。
終於,公司的業務開始走上正軌,前端團隊也已經有二三十人了,胸懷大志、急他人所不急的你覺得再這樣野蠻生長下去是肯定不行的,靠堆人力去滿足快速發展且多變的業務需求是非常低效且低階的方式,必須要有技術上的基礎設施去支撐!即使公司層面不允許工作時間去做這種長遠看來對公司是百利而無一害的事情,也要去做,就業餘時間去做!
在所有基礎設施中,最初級、最能直接體現出開發提效成果的,就是高度抽象的 UI 框架。經過了不知多少個的「下班後」和「週末」,可算搞出了個能夠滿足一定業務場景的,在自己負責的幾個應用中初見成效。
正當你為自己所做的事情如期望中那樣得到了收益而感到欣慰時,突然有人冒出來質疑你所做的事情,並且有可能就是前端團隊中的。還好有其他人對你做的事表示認可,覺得有價值,讓你有動力在這件事上繼續下去。也許他是個後端開發,願意去用,或願意幫你在部門中推廣。
你不斷地給 UI 框架增加新的功能,並想方設法去改造舊系統。在公司擴充業務所需要的新應用和以前老應用的維護中,你所做的東西確確實實節省了不少人力和資源。在有新的一批後端開發入職時,還會邀請你在新人培訓上給他們講解如何使用你所開發的 UI 框架輔助完成工作。這結結實實地打了當初質疑你的人的臉。
後臺系統頁面的常見模式就是供資料 CRUD 的列表頁、表單頁和詳情頁,當把支撐這些場景的互動和資料處理的核心邏輯都已經抽象了之後,你發現再怎麼完善 UI 框架也不會有像之前那樣比較明顯的效率提升,頂多是優化了互動和開發體驗,使功能更穩定而已。
你陷入了思考:「該做些什麼才能繼續為開發提效呢?」
之前做的 UI 框架,是對互動邏輯和資料邏輯進行了高度封裝,並提供了大量的 CSS class 和工具方法。雖然使在做頁面時可以少寫很多 CSS 和 JS 程式碼,但對於 HTML 程式碼來說並沒有減少。
貌似找到了該突破的點,但要怎麼去做呢?
左思右想,你突然靈光乍現,想起了自己曾經用過的基於「世界上最好的語言」開發的部落格系統——WordPress。既然後臺系統頁面如此模式化,何不效仿 WordPress 將不易變的部分作為「主題」,易變的部分作為「文章」?
這樣做會帶來另外一個好處,就是將頁面程式碼資料化了,有什麼純前端的問題修改就只是資料修正,而不用走冗長繁雜的運維釋出流程。日後如果公司有了自己的設計語言,再加入視覺化搭建的特性,業務後臺系統的開發和維護前端就不太用參與了!
理想情況下,產品經理用已有物料拖拖拽拽生成「原型」,該「原型」就是最終介面;業務功能確定後,後端開發定模型、寫介面,然後配置介面的資料展示。這樣一來,業務系統迭代的整個過程中,基本可以忽略前端這個角色了。
那麼前端幹什麼呢?在這樣的協作模式下,前端的主要工作就是完善物料庫,並且讓產品經理和後端開發使用起來更方便。這種提效方式所帶來的收益,與開發 UI 框架相比,根本不是一個層次的,想想都覺得興奮!
然而,理想的豐滿遮不住現實的骨感。聽到你的想法的人,要麼質疑地問你一些問題,要麼嘴上表示支援心理暗地譏笑——不想些怎麼讓業務發展起來的事情,整天想什麼亂七八糟、花裡胡哨的東西!
你覺得心裡憋屈,認為他們目光短淺,看不透本質。但為了自己所認為所堅信的「正確」,就算沒有人在心理上或行動上有所支援,也要朝著那個方向努力,嘗試做一把!
經過一段時間的折騰,你開始感到有些做不下去了。一方面是因為,雖然 Node.js 的出現讓前端開發人員也能夠開發服務端,但資料庫等服務端開發領域所需知識和思維方式匱乏,致使設計很不合理,寫出來的程式也不好;另一方面,公司層面不期望你投入較多的時間在短期內對業務發展沒有太大幫助的事情,就連 KPI 的指標設定都是很業務化的,等 KPI 評分時分數肯定很低。
在這家公司裡,你也算是「老員工」了,對公司的品性也較為深刻了解,自覺自己所認為所堅信的「正確」在這裡得不到認真對待,至少很長一段時間之內是,你甚是失望,甚至絕望。其實,你早如此感覺,只是不願面對,總是希望自己的信念能夠多多少少影響到組織的認知,然而徒勞。
從 UI 框架到頁面資料化,在做這些事情時你都是獨自一人、孤軍奮戰,忽然心裡感到一絲悲涼。你最終黯然離開,想去大廠裡去看看,也許那裡能夠讓你實現技術理想。
當你真正進了大廠,而且是個業務部門時,你會發現做的事情和之前並沒太大差別,仍然是業務為重。不同的是,可能你的領導和身邊的同事,對你的想法是真心認同的,他們會盡力支援你想做的事情,併為你提供幫助。
你幡然醒悟:無論在小廠、中廠還是大廠,只要是在業務部門,UI 框架、命令列工具基本就是在技術上所能做的極限,要想更上一層,就得在平臺部門。
提效方式
前面多次提到了「提效」這個詞,它是什麼?簡單粗暴地講,就是縮減業務需求的研發時間,這是所有開發人員所追求的。如果有可能,只需需求方自己動動手操作下就完成。
那麼該如何提效呢?我所能想到的,大概有:
- 基於各檢視層庫的具有一致 API 的 UI 框架;
- 能夠覆蓋整個研發流程的命令列工具;
- 將一份原始碼編譯/轉譯成不同目標平臺程式碼的工具;
- 頁面資料化並支援視覺化搭建的平臺。
這幾點,每個展開往深了弄都是很有價值的事情,需要耗費很多心血,甚至可以作為一個產品或開一家公司了!
前端架構
在繼續往下進行之前,先讓我們來稍微探討下「前端有架構嗎?」這個問題。
有架構嗎?
「架構」是什麼?架構是一組抽象概念,像「人」,像「寵物」,讓你不必關注他是誰,它是什麼動物;架構是一張圖,讓你能夠清楚地瞭解不同事物是怎麼歸類的,它們之間是如何聯絡到一塊,如何進行協作的;架構是指導思想,告訴你什麼該做、什麼不該做,指引你把程式碼寫到正確的地方;架構是一套方法論,讓你知道在哪些場景下遇到哪類問題該怎樣去解決……
引用維基百科的話——
Software architecture refers to the fundamental structures of a software system and the discipline of creating such structures and systems. Each structure comprises software elements, relations among them, and properties of both elements and relations. The architecture of a software system is a metaphor, analogous to the architecture of a building. It functions as a blueprint for the system and the developing project, laying out the tasks necessary to be executed by the design teams.
基於上述描述,如果前端開發只是單純的靜態頁面,即只有 HTML 和 CSS,或 JS 只作為新增特效使用,不運算元據,沒有通訊,那麼可以說「前端沒架構可言」。但,現在從事前端開發的人,有幾個人的工作是這樣的呢?
我想,從事前端開發的你的工作不是做頁面,而是應用開發吧?那麼,架構就是必不可少的了。你也許會疑惑:「我連這聽起來逼格很高的詞具體是指啥都不知道,怎麼可能會有?!」
之所以無所察覺,是因為你沒有刻意去思考並進行架構設計。想想看,你是不符合以下情形:
- 根據社群裡總結的最佳實踐,或者與他人交流時受到啟發,在開發時將程式碼邏輯拆分成不同模組,並將幾個具備一些相同特徵的模組放到一個目錄下;
- 用 Umi 或 Vue 全家桶開發單頁面應用。
這兩種情況都可以說是使用了分層架構模式,前者是你無意間進行的,後者是人家幫你做好了的。
好的架構?
既然「前端有架構嗎?」這個問題的答案是肯定的,「什麼樣的架構是好架構?」就成為了下一個問題。
在說「什麼樣的架構是好架構?」之前,先插入另外一個問題,有興趣的話可以先行思考下:一個足夠複雜的前端框架,與瀏覽器、作業系統之間有什麼相同點?
迴歸正題。我認為一個好的架構應該是這樣的——
幫公司更輕鬆地賺錢。這點是最重要的,對於一個企業來說,如果軟體不能讓自己賺錢,為什麼要用它?幫助公司賺錢的方式無非就兩種,「開源節流」。「開源」比較難,需要了解行業並洞悉商機,對人本身資質的要求太高;「節流」相對就簡單了,減少研發投入,即上文所說的「提效」。
第二重要的,就是「穩定」。一個差不離兒的架構,至少得能支撐業務發展三五年吧?雖然公司未必能活那麼久。這就需要在做架構設計時能夠面向未來:一是業務的未來,二是技術的未來。面向未來的架構必須擴充套件性好、足夠靈活,這樣才有可能應對各種業務場景及突如其來的業務變化。
以上是我覺得一個好的架構的兩個核心標準,每個點都會牽扯到很多事情,就不在此多說。
在對一個系統進行架構設計時,會用到多種架構模式,如:分層模式、管道和過濾器模式、微核心模式、微服務模式、MVC/MVVM 模式等。在實現時又會用到多種設計模式、資料結構與演算法。
因此,要學習並掌握它們,然後根據(潛在)業務目標與(潛在)應用場景去選擇最適合的運用到架構設計和框架實現當中。
核心原則
在做前端架構時,我認為該遵守幾個基本原則——
第一個是「以不變為中心」。
軟體開發的本質就是運算元據,放在 web 開發的場景,後端是儲存、獲取資料,前端是收集、展示資料。
資料在前、後端流轉時,資料的基本形態不會變:基本型別、物件、列表;資料的傳輸協議也不會變:HTTP、WebSocket。在前端開發中,離它們越遠、離 GUI 越近的東西就越容易變。
所以,首先要做的就是梳理出哪些東西是不易變化的,哪些是很容易就變了的。
第二個是「各層皆可替換」。
將根據易變性梳理出的模組按職責進行分層,定義好層與層之間的對接協議(介面)。除了因自身進化需要,對接協議是基本不會變的,也不應去改變。以此為前提,各層實現可在業務需要或技術升級時進行替換。
第三個是「檢視層儘可能薄」。
檢視層的職責是展示資料,理應只有互動邏輯,而大多數前端在寫 UI 元件時會摻雜較多的業務邏輯,使檢視層變得很是厚重、臃腫。這樣一來,業務邏輯不利於複用,也會增加檢視層技術的遷移成本。應將業務邏輯進行抽象,並提取到領域層,讓檢視層保持純粹。
由於檢視層的易變、多樣,並想讓它儘可能薄,最好有什麼方式能夠增加它訪問邏輯層的成本,就像前端只能通過網路請求訪問後端一樣。
忽然想到在做業務開發時有遇到過這種架構,你有印象嗎?沒錯,就是微信小程式!微信小程式的架構是將邏輯層與檢視層放到不同的執行緒中執行,從而做到了天然隔離,它們之間交流的媒介只有「資料」:
微信小程式是建立在客戶端應用提供一些原生能力基礎之上的,那麼在瀏覽器中能夠達到相同或類似的效果嗎?當然可以!瀏覽器提供原生能力,檢視層執行在 iframe 中,邏輯層則在 web worker 裡:
覺不覺得這很像「微前端」架構——據我理解,簡單來說就是一種能夠讓不同技術棧的模組同時執行在瀏覽器中,它們可以是元件也可以是應用,並且相互之間能夠通訊、協同工作的架構模式。
基於這種架構,可以開發出一個類似於瀏覽器、作業系統的「超級 app」,成為平臺級應用。
如果你在平臺部門,上文說的也許就是你要面對的事情。
開源專案
前段時間,某廠的前端團隊開源了一套元件庫,當時我在想:如果做不到比 Ant Design 優秀,開源個元件庫的意義在哪?
出自螞蟻金服的 Ant Design,無論從設計(視覺設計、程式碼設計,各種設計)還是從實現來看都已經很優秀了,API 設計十分考究,國內很難有出其右的作品。
如果說在某個檢視層技術或某個端沒有其對應的實現,與其自己從頭造輪子,還不如實現一個在那個檢視層技術或那個端的 Ant Design 版本。
之前我一直認為經過幾十年的發展,GUI 的互動形式已經相對固定,不太會有什麼突破,如果已經存在了一套很是優秀的互動模式庫,後來者若是沒有什麼能夠與其抗爭的亮點,在競爭上無疑是以卵擊石。
直到聽到叔叔說:
開放的意義並不是程式碼,而是有自身對互動的理解,如果做不到這點,那開放元件庫就沒有意義。
一開始沒怎麼理解這句話的內涵,之後的幾天時不時會想到這句話,琢磨其中的含義。之後忽然明白了——這不就跟寫文章一樣嗎?!寫作難道是為了讓別人看到自己的文字?當然不是!是想用文字記錄並表達自己對這個世界、人、事、物的理解。難道已經有人寫過相同或類似觀點的文章,且寫得十分好,自己就不能寫了嗎?當然不是!
原來如此。
其實任何帶有創作性質的行為都是一樣的,都是通過某個途徑來表達自己的思想,寫文章是,寫程式碼是,繪畫是,做菜也是。正如荒木老師的書上所說——
最近,我要開始做一個「大」專案。實際是前幾年就想做的,只不過當時沒想好到底要做些什麼,但核心理念是一致的——反混沌!連專案名都起好了,就叫「Anti-chaos」。
為什麼要做這麼一個專案?還不是因為前端圈太混亂?雖然與前些年相比稍微好了那麼一點,但跟 Java 圈相比,亂太多了。我希望「Anti-chaos」能成為盤古之斧,劈開混沌,清者為天,濁者為地。
那麼「Anti-chaos」要做些什麼?就如剛才所說,這是一個「大」專案,因為它基本要覆蓋當前前端開發的方方面面。
我並不是想開發一個大而全的框架,而是要遵照「反混沌」的思想拆分成多個小專案,每個都是解決某個固定場景的問題,它們可以組合並擴充套件成適合某個團隊、企業的解決方案,從而使前端開發乃至前端圈變得更加有序。
之前我也是基於類似的想法,想讓「前端工程師」這個職業相關的一些事情變得更加標準、有序,然而這件事操作起來實在是太困難了,比安靜地寫程式碼難上不知道多少倍,所以目前處於擱置狀態。等「Anti-chaos」有所成效之後,再看情況是否重啟那個專案吧。
思想總結
作為前端工程師,在業務部門所能接觸到的技術以及眼界的提高是有限的,一是在做業務時用不上什麼太前沿的技術,二是業務部門的性質不會允許也沒有資源讓你做太多深入的思考和嘗試。
要想真正地提升自己的技術能力和眼界,最好還是去平臺部門吧!剛開始時也許會覺得很吃力,這是因為你為了適應環境而在進行思維模式的轉變。等你適應了,你就會發覺自己在思考問題時與後端越來越接近,也會越來越覺得無論做前端還是做後端,所需要的知識和能力是差不多的,只是要解決的問題不同。
一個人的水平不能用年齡和年限去衡量,要看他有多少經歷,都經歷過什麼。
本文主要闡述了我最近一段時間對前端開發、前端架構以及開源專案等方面的思考及現階段的理解,不一定對,但是我目前的見解。
正所謂——
參禪之初,看山是山,看水是水;禪有悟時,看山不是山,看水不是水;禪中徹悟,看山仍然是山,看水仍然是水。
以上。
歡迎關注微信公眾號以及時閱讀最新的技術文章: