天天看點

grunt html子產品化管理插件,淺談前端架構的工程化、子產品化、元件化、規範化

架構的目的是什麼?答案是提升品質和效率。

一個項目組成分為 前端,服務端。傳統的前端項目用三劍客 javascript html css 就傳統的項目結構已經不能滿足日益壯大的大型應用的需求了。現在前端的生态圈很繁榮,各種架構,元件的出現。讓前端發展迅速,快速開發已經成為了前端的一個标準。如果你想建構一個易維護,代碼簡潔,性能優化程度高的項目就離不開前端的架構。這也就解疑了架構是不是必須的?

架構的目的是什麼?答案是提升品質和效率。

在沒有架構的情況下:舉個例子:一個程式員來寫各個頁面,但是不同的人寫代碼風格不一樣,代碼也有很多缺陷,甚至低級的bug。很難更新項目用到的技術。如果濫用元件庫和各種架構就會導緻項目體積的臃腫,很難和前端新出現的技術接軌,沒辦法跟上新規範。新技術無法得到引入,技術無法統一,使得團隊的整體技術能力無法得到提升,也無法提供技術上的通用解決方案,從團隊的角度來考量的話,效率是非常低下的。

同時,因為技術過于陳舊,再加上代碼沒有統一規範,導緻碰到頁面業務邏輯比較複雜,或者對老頁面進行維護的時候,産生Bug的機率非常高,産品品質堪憂

那應該怎麼進行架構呢?架構的目的是制定标準,提升品質和效率。

• 架構是一個抽象的過程,它是架構師根據自己的經驗對大量具體的業務項目進行分析,發現其中的規律,抽象出具體的規範,最終又應用于具體的業務項目中去。比如常說的MVVM就是一種規範。

• 要把跟業務無關的問題都在架構層面處理掉。比如代碼壓縮,打包這種工程化的問題都要在架構層面統一解決的。要做到業務的歸業務,架構的歸架構。

• 架構要考慮到可以友善團隊成員提供和使用通用技術解決方案。比如分頁元件這種。

• 架構設計的時候要綜合考慮目前的主流技術跟自己業務系統的實際情況。因為前端正處在高速發展,各種新技術,工具,插件,架構層出不窮,要結合項目實際情況運用已經成熟的技術,避免跳坑。。

合理的架構應該是怎麼樣的?概括幾點就是:子產品化,元件化,工程化,規範化。

1、淺談工程化

工程化就像是百葉箱一樣,減少人的操作,把工作所需要的工具做到的标準化,工作的流程做到的标準化。同時把很多重複的工作交給了代碼來做,保證高質,标準統一。

先從工具入手,工程化包括哪些方面:

• 子產品化與元件化: npm, es6,seajs, react/angularjs/Vue

• 代碼版本管理: git

• 代碼風格管理: jscs, editorconfig

• 代碼編譯: babel, less,sass,scss, imgmin, csssprit, inline-svg

• 代碼品質管理 (QA): eslint, mocha

• 代碼建構: webpack

• 項目腳手架: yeoman

• 持續內建/持續傳遞/持續部署: jenkins

• 本地化與國際化

進行工程化:

• 在配置初始項目檔案結構和基本檔案依靠指令行(工具)自動生成。

• 确定代碼規範,縮進,換行,以及各種預編譯工具less,coffee,保證輸出代碼的标準一緻

• 對JS檔案是否規範化,進行單元測試,不用手動複制到jshint上去檢測,現在配置grunt監聽檔案變動自動檢驗顯示檢驗結果還可以通過配置建構工具自動重新整理浏覽器實作檔案實時變動監聽。

• 以前壓縮合并檔案用手工複制到壓縮工具然後複制到一個檔案裡面,現在配置一下 grunt,gulp可以做自動任務,實時編譯,并且監測檔案改變而做出響應。

• 以前釋出到伺服器上,要手動使用 FTP 軟體上傳,現在也可以用工具自動打包上傳。

2、淺談子產品化

通行的JavaScript子產品規範主要有兩種:CommonJS和AMD

CommonJS

我們先從CommonJS談起,因為在網頁端沒有子產品化程式設計隻是頁面JavaScript邏輯複雜,但也可以工作下去,在伺服器端卻一定要有子產品,是以雖然JavaScript在web端發展這麼多年,第一個流行的子產品化規範卻由伺服器端的JavaScript應用帶來,CommonJS規範是由NodeJS發揚光大,這标志着JavaScript子產品化程式設計正式登上舞台。

-定義子產品

根據CommonJS規範,一個單獨的檔案就是一個子產品。每一個子產品都是一個單獨的作用域,也就是說,在該子產品内部定義的變量,無法被其他子產品讀取,除非定義為global對象的屬性。

-子產品輸出

子產品隻有一個出口,module.exports對象,我們需要把子產品希望輸出的内容放入該對象。

-加載子產品

加載子產品使用require方法,該方法讀取一個檔案并執行,傳回檔案内部的module.exports對象。

不同的實作對require時的路徑有不同要求,一般情況可以省略js拓展名,可以使用相對路徑,也可以使用絕對路徑,甚至可以省略路徑直接使用子產品名(前提是該子產品是系統内置子產品)

AMD

AMD 即Asynchronous Module Definition,中文名是異步子產品定義的意思

requireJS主要解決兩個問題

1、多個js檔案可能有依賴關系,被依賴的檔案需要早于依賴它的檔案加載到浏覽器

2、js加載的時候浏覽器會停止頁面渲染,加載檔案越多,頁面失去響應時間越長

CMD

CMD 即Common Module Definition通用子產品定義,CMD規範是國内發展出來的,就像AMD有個requireJS,CMD有個浏覽器的實作SeaJS,SeaJS要解決的問題和requireJS一樣,隻不過在子產品定義方式和子產品加載(可以說運作、解析)時機上有所不同

AMD與CMD差別

最明顯的差別就是在子產品定義時對依賴的處理不同

1、AMD推崇依賴前置,在定義子產品的時候就要聲明其依賴的子產品

2、CMD推崇異步依賴加載的,隻有在用到某個子產品的時候再去require

AMD和CMD最大的差別是對依賴子產品的執行時機處理不同,注意不是加載的時機或者方式不同。很多人說requireJS是異步加載子產品,SeaJS是同步加載子產品,這麼了解實際上是不準确的,其實加載子產品都是異步的,隻不過AMD依賴前置,js可以友善知道依賴子產品是誰,立即加載,而CMD就近依賴,需要使用把子產品變為字元串解析一遍才知道依賴了那些子產品,這也是很多人诟病CMD的一點,犧牲性能來帶來開發的便利性,實際上解析子產品用的時間短到可以忽略。

具體子產品化比較可以檢視:前端子產品化

webpack時代

webpack的優點:

1.require.js的所有功能它都有

2.編繹過程更快,因為require.js會去處理不需要的檔案

3.還有一個額外的好處就是你不需要再做一個封裝的函數,require.js中你得這樣

define([‘jquery’], function(jquery){})

4.現在你需要一個很大的封裝去定義每個子產品,然後你需要在在require.js的配制檔案中将每個子產品的路徑都配出來,用過requirejs都會遇到的好繁瑣

對比requirejs seajs webpack特有的屬性:對 CommonJS 、 AMD 、ES6的文法做了相容

對js、css、圖檔等資源檔案都支援打包(css都可以合成多個css檔案包,sass和less雖然也是子產品化的加載合并,可是css和js分離的關聯不大,這裡的css可以和js有更大的關聯,更細緻區分加載的js)

串聯式子產品加載器以及插件機制,讓其具有更好的靈活性和擴充性,例如提供對CoffeeScript、ES6的支援

有獨立的配置檔案webpack.config.js

可以将代碼切割成不同的chunk,實作按需加載,降低了初始化時間

支援 SourceUrls 和 SourceMaps,易于調試

具有強大的Plugin接口,大多是内部插件,使用起來比較靈活

8.webpack 使用異步 IO 并具有多級緩存。這使得 webpack 很快且在增量編譯上更加快

9.雙伺服器模式

3、淺談元件化

保證元件的封閉性。因為JS方面是子產品化的。元件的功能界限問題。也就是什麼是應該在元件内部實作,什麼是應該由元件的調用者來實作的。對元件功能界限的定義是隻負責UI相關的功能,所有的業務邏輯都是從調用者傳遞過的。也即是寫在param.js。是以param.js檔案是非常重要的一個檔案,裡面基本包涵了這個頁面所有業務處理邏輯。很顯然,随着頁面業務邏輯變的複雜,js檔案将會變得越來越大。沒關系,把不同的元件參數分拆到不同的js檔案裡面去實作,然後建個專門的檔案夾把它們組織起來。

4、淺談規範化

項目目錄結構非常清晰。當進行開發的時候,哪些代碼應該放到哪裡都進行了明确的規定,并且每個檔案的功能都盡量清晰并且單一。

比如:

頂層目錄結構如下圖:

grunt html子產品化管理插件,淺談前端架構的工程化、子產品化、元件化、規範化

1、src檔案夾存放的是所有的的源代碼和其他靜态資源(比如圖檔,iconfont)。

2、dist檔案夾存放的是所有編譯後的代碼。

3、build檔案夾存放的是所有工程化所需要的代碼。

4、document檔案夾當然存放的文檔。

下面重點看下src目錄結構,如下圖:

grunt html子產品化管理插件,淺談前端架構的工程化、子產品化、元件化、規範化

1、app檔案夾裡的每一個子檔案夾代表了一個頁面,每個頁面所用到的所有靜态資源都存放在這個子檔案下面(除了引用的公共資源以外),建構的時候,每個子檔案夾會生成自己的靜态資源供頁面引用。

2、common檔案夾裡面的所有代碼在建構的時候會單獨生成js檔案和css檔案供頁面引用。是以一個頁面會引用兩個js和兩個css.裡面存放的是每個頁面都會用到的一些共用資源。比如觸屏端使用了react,那麼跟react相關的那些包就會放在common裡面。

3、components檔案夾裡面存放的是共用元件,每一個子檔案夾代表了一個元件。有可能是通用的功能元件,比如分頁元件,Loading元件,ModalDialog元件。也有可能是一個通用的業務元件,比如站點通用頭部,通用footer,通用分享元件。注意,在其他地方引用這些元件時,是不需要寫相對路徑的,直接寫元件名字就可以了,比如import pager from ‘pager’。這樣對使用者更友善。

4、lib檔案夾存放的是通用的js類庫。比如檢測浏覽器用的browserDetect.js,處理日期用的dateUtil.js。同樣的,在其他地方需要引入這些JS時,也不需要寫相對路徑,直接寫JS的名字就可以了。比如import{isIE} from ‘browserDetect’。

5、style檔案夾裡面存放的一些公用的sass資源。比如function,mixing, variable。其他的sass檔案需要引入這些資源的時候,使用方式跟使用通用js一樣,直接@import “base.scss”即可。

架構是個不斷完善的過程,而把架構尤其是跟規範相關的部分落實到具體業務系統裡面更是個團隊不斷磨合的過程。它最終考驗的,同時也是最終磨合出來的是團隊的成熟度。

原文連結:http://outofmemory.cn/html/front-end-project-component