元件化——前端程式設計的選擇
一、前端為什麼要做元件化
在大型軟體系統中,web應用的前後端已經實現了分離,而隨著REST軟體架構的發展,後端服務逐步傾向於微服務,簡單來說就是將一個大型後端服務,拆分成多個小服務,它們分別部署,降低了開發的複雜性,而且提高了系統的可伸縮性。而前端方面,隨著技術的發展,開發的複雜度也越來越高,傳統開發模式總是存在著開發效率低,維護成本高等的弊端。
傳統開發方式效率低以及維護成本高的主要原因在於很多時候是將一個系統做成了整塊應用,而且往往隨著業務的增長或者變更,系統的複雜度會呈現指數級的增長,經常出現的情況就是一個小小的改動或者一個小功能的增加可能會引起整體邏輯的修改,造成牽一髮而動全身。
針對此弊端,其實業界早就有了一些探索,我們希望一個大且複雜的場景能夠被分解成幾個小的部分,這些小的部分彼此之間互不干擾,可以單獨開發,單獨維護,而且他們之間可以隨意的進行組合。就拿電腦主機來說,一臺整機包括CPU,主機板,記憶體,硬碟等等,而這些部件其實都是由不同的公司進行生產的,他們彼此之間根據一套標準分別生產,最後組裝在一起。當某個部件出現問題時,不需要將整臺主機都進行維修,只需要將壞的部件拿下來,維修之後再將其組合上就可以了。這種化繁為簡的思想在後端開發中的體現是微服務,而在前端開發中的體現就是元件化。
隨著React,angular等以元件(指令等)為主的優秀前端框架的出現,前端元件化逐漸成為前端開發的迫切需求,當然這一迫切需求也逐漸成為一種主流,一種共識,它不僅提高了前端的開發效率,同時也降低了維護成本。開發者們不需要再面對一堆複雜且難閱讀的程式碼,轉而只需要關注以元件方式存在的程式碼片段。
那麼前端元件化開發都經歷了哪些階段呢?
二、 前端元件化開發發展之路
1、互動少的靜態頁面時期:公共模組和CSS
這是一個很古老的時代,那時的前端頁面就是一些基本的HTML標籤以及JS和CSS,頁面上大部分都是一些靜態的文字,就在這個時期,前端JS和CSS已經出現了元件化,或許更多的應該成為模組化,即開發者把不同模組的或者公共的JS和CSS放在不同的檔案中,然後在頁面引入並使用,這種方式也沿用至今。
2、繁瑣的早期動態頁面時期:動態引入
由於靜態頁面不能在頁面上儲存資料,閱讀者也不滿足於基本的頁面互動,更希望頁面能夠活起來,且能夠把互動的資料儲存起來,於是出現了很多服務端技術,比如ASP,JSP。這些技術的出現使得前端頁面活起來了,使用者可以根據自己的需求進行資料的互動。
然而這時的頁面上充斥著業務邏輯,隨著業務邏輯的增多,頁面的內容也越來越多,越來越複雜。在這個時期前端元件化開發得到了一定的發展,開發者已經不滿足於簡單的將JS和CSS檔案模組化,開始把一些公用的頁面邏輯獨立開來,然後通過頁面動態引入的方式進行使用,比如公共的頁面頭(header)和尾(footer)以及資料庫的連線(DatabaseConn.jsp)等。
3、後端為主的MVC時期:Tag標籤
由於早期動態頁面時期的業務邏輯都寫在頁面上,隨著邏輯的增多,頁面越來越複雜,維護起來也越來越難。於是以servlet為代表的MVC時代逐漸登上歷史舞臺,這時頁面上的邏輯都被轉入到servlet中,使得View層的表現更加簡潔,也更加的易於閱讀,從而達到了開發的分層。
而隨著Struts以及Spring的出現,MVC的開發方式達到鼎盛時期,前端View層的展現也變得越來越簡單,沒有了複雜的業務邏輯,前端的元件化方式主要是taglib標籤,比如jsp標籤,Struts標籤等,把HTML程式碼和業務邏輯打包成一個標籤,然後使用者直接放置在想要的地方,就可以了。但這個時期,整個WEB應用的開發輕前端重後端,那些taglib標籤也都是JAVA程式碼編寫的。
4、前端Ajax時期:JS大行其道
由於MVC時期的輕前端重後端的思想,前端頁面主要以表格的形式展現,如果想要一些很炫的效果,實現起來就比較複雜了,往往要寫一大堆的程式碼,而且很難閱讀。AJAX作為早已經出現的技術在這個時候越來越受到開發者的青睞,於是出現了很多的JS框架,比如JQuery-UI, easy-UI,miniUI以及大名鼎鼎的ExtJS。
這些JS框架的出現使得前端元件化的開發到達了一個新的高度,利用封裝Dom,AJAX以及頁面互動的方式,一個個的很炫的元件出現了,開發者可以隨意的將這些元件應用的頁面中,開發變得簡單的同時頁面也變得越來越好看。由於這些互動都由JS來完成,執行在瀏覽器端,也大大的減少了服務端的壓力,同時也提高了效能。
5、前端MV*時期:自定義元件
隨著時間的推移,開發者發現,如果想要修改這些(ExtJS,miniUI)JS框架中的元件是非常困難的,因此開發者希望能夠很容易的自定義一些元件。這時以Angular,React為代表的可以自定義元件的JS框架出現了。這些框架的出現不僅可以讓開發者自定義元件,而且可以讓開發者將已經存在的元件進行封裝。
不僅如此,由於有了npm以及bower這些包管理庫,開發者可以很容易的將自己開發的元件publish到這些庫中,在使用時只要把他們下載下來(比如npm install)就可以直接使用了。比如:
以上的元件化基本以HTML和JS為主,那麼CSS怎麼做元件化呢?
6、CSS元件化:less和sass
前面講了CSS的模組化基本上是將實現某一模組Dom樣式的CSS放在不同的檔案中,顯然隨著WEB應用的發展,開發者已經很不滿足於這種簡單的模組化了。 其實關於CSS的元件化,業界也早就已經有了很多探索,比如less,sass等。那麼為什麼CSS也要元件化呢?
我們知道CSS是一種扁平的結構,一個Dom可能對應著一個CSS樣式,而這些CSS樣式很有可能出現公共的部分,那麼提取這些公共的部分也就實現了CSS的元件化,在諸如less和sass出現之前,開發者都是把公共的CSS樣式寫成一個個公共class,但是這樣之後CSS檔案的閱讀性就變得困難了,當然也不容易修改。而less和sass出現之後,使得CSS的程式設計可以定義變數,可以實現繼承,CSS內容的結構也變得更加清晰,提高了CSS檔案的閱讀性,更容易讓人理解,修改起來也變得簡單。
三、前端元件化的4個原則
前面講了元件化開發的發展過程,那麼我們該怎麼做元件化呢?我認為元件應該遵守以下幾個原則:
-
標準性
任何一個元件都應該遵守一套標準,可以使得不同區域的開發人員據此標準開發出一套標準統一的元件。
-
組合性
元件之前應該是可以組合的。我們知道前端頁面的展示都是一些HTML DOM的組合,而元件在最終形態上也可以理解為一個個的HTML片段。那麼組成一個完整的介面展示,肯定是要依賴不同元件之間的組合,巢狀以及通訊。
-
重用性
任何一個元件應該都是一個可以獨立的個體,可以使其應用在不同的場景中。
-
可維護性
任何一個元件應該都具有一套自己的完整的穩定的功能,僅包含自身的,與其它元件無關的邏輯,使其更加的容易理解,使其更加的容易理解,同時大大減少發生bug的機率。
四、總結與實踐
當然元件化開發也並不是這麼簡單就能實踐的。
-
對開發者的能力有一定的要求,比如傳統開發方式可能只要求開發者懂HTML,JS,CSS這些就可以了,而元件化開發方式下還可能要求開發者掌握less,sass,或者ES6等的語法,以及webpack,glup等的前端打包以及構建工具。不過另一方面,哪個開發者不希望自己能掌握更多的本領呢?
-
技術選型,當前前端元件化框架可以說是百家齊放,這就要求技術經理或者架構師具有超前的前瞻性,根據專案需求以及框架的未來發展進行分析選型。
以我們公司目前在做的專案《普元數字化企業雲平臺》為例,整個前端專案由上海和西安兩地的同事共4個人合作開發,在開發之初就確立了要採用一套統一的標準以減少異地開發的溝通成本,以及維護成本,顯然元件化開發可以很好的滿足此要求。
基於此,我們的前端使用的是Facebook的React技術,React的核心是使用元件定義介面的表現,它突出的就是開發元件化。 如下圖所示,介面上的任何表現都對應著元件。元件之間很好的遵守了元件化開發的幾個原則,不同區域的同事開發出的元件都如同同一個人寫的,大大降低了異地的溝通成本和維護成本,以及提升了開發效率。
元件化開發方式對比傳統開發方式: