從本質上講,所有Web應用都是一種運作在網頁浏覽器中的軟體,這些軟體的圖形使用者界面(Graphical User Interface,簡稱GUI)即為前端
随着Web業務日益複雜化和多元化,前端開發已由以WebPage模式為主轉變為以WebApp模式為主;現在随便找個前端項目,都已經不是過去的拼個頁面+搞幾個jQuery插件就能完成的了;工程複雜了就會産生許多問題,比如:如何進行高效的多人協作,如何保證項目的可維護性,如何提高項目的開發品質
前端工程化是前端架構中重要的一環,主要是為了解決上述大部分問題的,而前端工程本質上是軟體工程的一種,是以我們應該從軟體工程的角度來研究前端工程
要解決前端工程化的問題,可以從兩個角度入手:開發和部署。
1.從開發角度,要解決的問題包括:
提高開發生産效率/降低維護難度/減少請求數,降低請求量/減少重繪&回流
2.這兩個問題的解決方案有兩點:
制定開發規範,提高團隊協作能力
分治;軟體工程中有個很重要的概念叫做子產品化開發其中心思想就是分治
從部署角度要解決的問題主要是資源管理,包括:
代碼審查
壓縮打包:合并樣式/腳本檔案,合并背景圖檔,CSS3圖示/Icon Font/開啟GZip/優化靜态資源,jQuery->Zepto/閹割IScroll/去除備援代碼/圖檔無損壓縮/圖檔延遲加載/減少Cookie攜帶
增量更新
單元測試
要解決上述問題,需要引入建構/編譯階段
是以,我個人認為前端工程化主要應該從子產品化/元件化/規範化/自動化四個方面來思考:
簡單來說,子產品化就是将一個大檔案拆分成互相依賴的小檔案,再進行統一的拼裝和加載;隻有這樣,才有多人協作的可能
ES6之前,JavaScript一直沒有子產品系統,這對開發大型複雜的前端工程造成了巨大的障礙;對此社群制定了一些子產品加載方案,如CommonJS/AMD/CMD等,某些架構也會有自己子產品系統,比如Angular1.x
現在ES6已經在語言層面上規定了子產品系統,完全可以取代現有的CommonJS和AMD規範,而且使用起來相當簡潔,并且有靜态加載的特性
規範确定了,然後就是子產品的打包和加載問題:
1.用Webpack+Babel将所有子產品打包成一個檔案同步加載,也可以打成多個chunk異步加載
2.用SystemJS+Babel主要是分子產品異步加載
3.用浏覽器的
雖然SASS/LESS/Stylus等預處理器實作了CSS的檔案拆分,但沒有解決CSS子產品化的一個重要問題:選擇器的全局污染問題;按道理,一個子產品化的檔案應該要隐藏内部作用域,隻暴露少量接口給使用者,而按照目前預處理器的方式導入一個CSS子產品後,已存在的樣式有被覆寫的風險;雖然重寫樣式是CSS的一個優勢,但這并不利于多人協作;為了避免全局選擇器的沖突,各廠都制定了自己的CSS命名風格:
1.BEM風格
2.Bootstrap風格
3.Semantic UI風格
但這些都畢竟是弱限制,選擇器随着項目的增長變得越多越複雜,然後項目組裡再來個新人帶入自己的風格,就更加混亂了
是以我很贊同這句話:與其費盡心思地告訴别人要遵守某種規則以規避某種痛苦,倒不如從工具層面就消滅這種痛苦
Webpack的強大之處不僅僅在于它統一了JS的各種子產品系統,取代了Browserify/RequireJS/SeaJS的工作,更重要的是它的萬能子產品加載理念,即所有的資源都可以且也應該子產品化
資源子產品化後有三個好處:
依賴關系單一化;所有CSS和圖檔等資源的依賴關系統一走JS路線,無需額外處理CSS預處理器的依賴關系,也不需處理代碼遷移時的圖檔合并/字型圖檔等路徑問題
資源處理內建化;現在可以用loader對各種資源做各種事情,比如複雜的vue-loader等
項目結構清晰化;使用Webpack後你的項目結構總可以表示成這樣的函數:<code>dest = webpack(src, config)</code>
首先,元件化≠子產品化;子產品化隻是在檔案層面上對代碼或資源的拆分,而元件化是在設計層面上對UI(使用者界面)的拆分;從UI拆分下來的每個包含模闆(HTML)+樣式(CSS)+邏輯(JS)功能完備的結構單元,我們稱之為元件
其實,元件化更重要的是一種分治思想;這句話就是說頁面上所有的東西都是元件,頁面是個大型元件,可以拆成若幹個中型元件,然後中型元件還可以再拆成若幹個小型元件,小型元件也可以再拆,直到拆成DOM元素為止;DOM元素可以看成是浏覽器自身的元件,作為元件的基本單元
傳統前端架構/類庫的思想是先組織DOM,然後把某些可複用的邏輯封裝成元件來操作DOM,是DOM優先;而元件化架構/類庫的思想是先來構思元件,然後用DOM這種基本單元結合相應邏輯來實作元件,是元件優先;其次,元件化實際上是一種按照模闆(HTML)+樣式(CSS)+邏輯(JS)三位一體的形式對面向對象的進一步抽象;是以我們除了封裝元件本身,還要合理處理元件之間的關系,比如(邏輯)繼承/(樣式)擴充/(模闆)嵌套和包含等,這些關系都可以歸為依賴
其實元件化不是什麼新鮮的東西,以前的用戶端架構,像WinForm/WPF/Android等,它們從誕生那天起就是元件化的,而前端領域發展曲折,是從展示頁面為主的WebPage模式走過來的,近兩年才從用戶端架構經驗中引入了元件化思想;目前市面上的元件化架構很多,主要的有Vue/React/Angular 2,其實Vue文檔中的對比其他架構一文已經講得很詳細了
子產品化群組件化确定了開發模型,而這些東西的實作就需要規範去落實,規範化其實是工程化中很重要的一個部分,項目初期規範制定的好壞會直接影響到後期的開發品質,我能想到的有:
目錄結構的制定
編碼規範
前後端接口規範
文檔規範
元件管理
Git分支管理
Commit描述規範
定期CodeReview
視覺圖示規範
其中編碼規範最好采取強制措施,配置git hooks可以實作Lint不過不能送出代碼等機制,因為人是靠不住的
作為多年程式猿,應該秉持的一個理念是:任何簡單機械的重複勞動都應該讓機器去完成
不要再用PS拼雪碧圖了,統一走Webpack吧;不要再用Icomoon了,統一走Webpack吧
自動化建構
自動化部署
自動化測試:前端自動化測試能夠提高代碼品質/減少人肉測試等,這些優點是不言而喻的;市面上前端測試架構有很多,選擇哪個都不會有太大問題
感悟:必須承認,人在被鞭子趕着的時候總比自覺向前走走得快