許多團(tuán)隊(duì)在制定前端工程方案時(shí)會加入腳手架模塊。雖然不同的團(tuán)隊(duì)對工程化的理解和實(shí)施有所差異,但是對于腳手架的定位基本是一致的:創(chuàng)建項(xiàng)目初始文件。這是一條看起來十分簡單地準(zhǔn)則,但是對于這條準(zhǔn)則應(yīng)該如何理解,如何實(shí)施卻并不是一件很簡單地事情。

在探索這條準(zhǔn)則的深度之前,我們不妨看看類似的一些成熟方案,比如Eclipse。這個(gè)大名鼎鼎的IDE軟件被很多Java和Android開發(fā)者使用。通過Eclipse創(chuàng)建一個(gè)新項(xiàng)目時(shí),它提供了豐富的配置項(xiàng),這些配置項(xiàng)可以歸納簡化為以下流程:選擇項(xiàng)目類型 -> 選擇項(xiàng)目目錄 -> 配置項(xiàng)目細(xì)節(jié) -> 最終確認(rèn) -> 完成。這是腳手架最基本也是必須具備的流程。從這個(gè)流程中可以總結(jié)出腳手架的本質(zhì):方案的封裝。

由此,我們明確了腳手架的定義:腳手架作用是創(chuàng)建項(xiàng)目的初始文件,本質(zhì)是方案的封裝。

當(dāng)然,腳手架創(chuàng)建項(xiàng)目流程之中還有很多細(xì)節(jié),并且前端項(xiàng)目的多樣性和復(fù)雜性更加為腳手架流程的實(shí)現(xiàn)增加了難度。這篇文章簡單闡述一下筆者的一些淺見,希望能夠給大家一些啟發(fā)。

1. 腳手架在前端工程中的角色

1.1 “用完即棄”的腳手架

之前寫過一篇淺析前端工程化,簡單介紹了前端工作流模型,簡化之后可以用下圖概括:
Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

腳手架在前端工作流中負(fù)責(zé)項(xiàng)目起始階段創(chuàng)建初始文件。與其他功能模塊不同的是,腳手架是一個(gè)完全“啟下”的模塊,它沒有任何前置依賴。創(chuàng)建完成項(xiàng)目初始文件之后,腳手架就再無用武之地了。

“用完即棄”的工作模式令腳手架的實(shí)現(xiàn)由很大的躍遷性。你可以用最簡單的復(fù)制粘貼就能完成腳手架的工作,而一個(gè)完備、成熟的腳手架即使提供了非常豐富的交互配置,最終目的也“只”是創(chuàng)建了一堆初始的項(xiàng)目文件。既然結(jié)果一樣,那為什么還要花費(fèi)時(shí)間和人力成品去開發(fā)復(fù)雜的腳手架方案呢?

躍遷是量子力學(xué)術(shù)語,意思是狀態(tài)發(fā)生跳躍式變化的過程。之所以將這個(gè)詞用在這里是因?yàn)楦叨韧陚涞哪_手架相比較低級形態(tài)的腳手架而言,能夠帶來質(zhì)的飛躍。

這是一個(gè)非?,F(xiàn)實(shí)的問題,互聯(lián)網(wǎng)產(chǎn)品迭代的快速節(jié)奏下,開發(fā)團(tuán)隊(duì)最注重的就是投入產(chǎn)出比,而腳手架的投入產(chǎn)出比“看上去”是最低的。環(huán)顧目前前端的工具生態(tài),最多的是構(gòu)建工具,當(dāng)然我們不可否定構(gòu)建確實(shí)是最復(fù)雜的功能。而腳手架工具是最少的,前端社區(qū)對腳手架的討論也非常稀少。你可能聽說過大名鼎鼎的yeoman,但是很難再想出第二個(gè)腳手架工具了。

單獨(dú)來看,腳手架可能并不具備很高的“性價(jià)比”,但如果你的團(tuán)隊(duì)有一套完整的前端工程體系,腳手架的作用就會被放大。前端工程體系的功能涵蓋范圍廣,封裝的方案類型多,對應(yīng)的配置項(xiàng)也非常復(fù)雜。而且,大多數(shù)前端工程體系的開發(fā)者并不是一線的業(yè)務(wù)開發(fā)者。對于業(yè)務(wù)開發(fā)者來說,這套工程體系就是一個(gè)黑盒,他們不需要了解其中的復(fù)雜原理,只需要知道如何配置即可。所以業(yè)務(wù)開發(fā)者的需求就是快速開發(fā)快速配置,并且生成的配置項(xiàng)跟項(xiàng)目要對應(yīng),既要滿足項(xiàng)目的功能需求,又不能有“混淆視聽”的冗余功能。

前端工程體系不是Vue、React這種開發(fā)框架,工程體系只是一種“服務(wù)”,是輔助性質(zhì)的。學(xué)習(xí)曲線應(yīng)該平緩,即使文檔再清晰易懂,也不應(yīng)該要求業(yè)務(wù)開發(fā)者去花時(shí)間學(xué)習(xí)各種細(xì)節(jié)。這就是腳手架要解決的切實(shí)問題,簡單說就是:

  • 快速生成配置;

  • 降低框架學(xué)習(xí)成本。

隨著前端工程體系越來越復(fù)雜,腳手架的角色會越來越重要。

1.2 腳手架需要具備的要素

1.2.1 執(zhí)行環(huán)境僅限本地

在討論實(shí)現(xiàn)一個(gè)腳手架要考慮哪些要素之前,我們不妨先看看腳手架的執(zhí)行環(huán)境?;仡櫱拔奶岬降暮喴浊岸斯ぷ髁?,最簡單的情形是:框架提供一套完整的本地工具鏈,腳手架、開發(fā)、開發(fā)服務(wù)器、構(gòu)建和部署測試都是在本地環(huán)境執(zhí)行,如下圖:
Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

進(jìn)一步的團(tuán)隊(duì)會搭建CI(持續(xù)集成)平臺,將構(gòu)建和部署功能遷移至云端,這樣做便于工作流程控制和代碼統(tǒng)一管理。如下圖:
Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

不論哪種工作流,腳手架始終是在本地執(zhí)行。

1.2.2 模式不固定

前端腳手架之所以沒有固定的模式,是由于不同的公司對于前端工程師的定位不固定。比如有些公司的前端仍然是“切圖仔”;有些公司的前端負(fù)責(zé)瀏覽器端的所有邏輯開發(fā)但是html模板層仍然由服務(wù)端工程師維護(hù);還有些比較前沿的團(tuán)隊(duì)提倡“大前端”,負(fù)責(zé)瀏覽器層與中間層(主要承載html的渲染功能)。前端工程師定位的不固定造成了前端項(xiàng)目模式的不固定,腳手架自然也具備了多樣性。

不論是哪種工作模式,一個(gè)優(yōu)秀的前端腳手架都應(yīng)該具備以下幾點(diǎn)要素:

  1. 豐富但不繁瑣的配置項(xiàng);

  2. 與其他功能模塊聯(lián)動,生成對應(yīng)的基本配置項(xiàng);

  3. 自動安裝依賴;

  4. 底層的高度可擴(kuò)展性;

  5. 支持多種運(yùn)行環(huán)境,比如命令行和Node.js API。

如何理解“豐富但不繁瑣”呢?舉個(gè)例子,假設(shè)構(gòu)建功能支持自動生成css sprites,配置項(xiàng)有兩個(gè):

  1. 是否啟用css sprites;

  2. 指定散列icon目錄。

腳手架在實(shí)現(xiàn)針對css sprites的配置項(xiàng)時(shí)是不是應(yīng)該將這兩個(gè)配置都開放給用戶配置呢?顯然是不需要的,腳手架只要開放是否啟用css sprites的配置項(xiàng)即可,因?yàn)檫@是影響這項(xiàng)功能最重要的一點(diǎn),散列icon的目錄即使用戶不配置,使用默認(rèn)的方案也不會造成任何不便。

另外,在實(shí)現(xiàn)腳手架時(shí)不應(yīng)該只看到當(dāng)前的需求,還應(yīng)該考慮后續(xù)需求的變更和新增。所以一個(gè)優(yōu)秀的腳手架應(yīng)該具備高度的可擴(kuò)展性,便于定制不同類型的方案。從這個(gè)角度來說,目前yeoman是做得最好的。

2. 開源前端腳手架方案剖析

明確了腳手架的基本工作模式,我們不妨看看目前業(yè)內(nèi)有哪些可以借鑒的案例。我們在這里介紹三種形態(tài)的腳手架:

  • sails是一個(gè)Node.js fullstack框架,其使用的sails generate腳手架主要是針對服務(wù)端代碼設(shè)計(jì);

  • 優(yōu)酷PHP中間層框架是筆者前團(tuán)隊(duì)使用的開發(fā)框架,目前并未開源。其使用的腳手架相對sails來說比較簡單,只能創(chuàng)建一個(gè)完整的webapp,包括Controller層和瀏覽器層代碼;

  • yeoman是廣為人知的開源腳手架工具,它本身不提供任何直接創(chuàng)建文件的功能,而是一個(gè)腳手架底層框架,你可以定制自己的腳手架實(shí)現(xiàn)。

其中兩個(gè)是開源項(xiàng)目,大家可以在Github上獲取對應(yīng)的源碼。

2.1 sails - Node.js fullstack框架

sails是一個(gè)Node.js全??蚣?,服務(wù)端使用MVC架構(gòu)。sails generate是sails的腳手架模塊,默認(rèn)可以創(chuàng)建以下幾種模塊的初始代碼:

  • app - 創(chuàng)建一個(gè)新sails項(xiàng)目;

  • api - 創(chuàng)建一對model和controller;

  • model - 創(chuàng)建一個(gè)model;

  • controller - 創(chuàng)建一個(gè)controller;

  • adapter - 創(chuàng)建一個(gè)adapter;

  • generator - 創(chuàng)建一個(gè)腳手架模板。

sails框架中的Adapter可以簡單理解為簡化model操作API的映射適配器。

大家注意最后一種類型:generator。sails在默認(rèn)的腳手架基礎(chǔ)上,開放了自定義腳手架模板的API

sails默認(rèn)的腳手架大都是針對服務(wù)端代碼的,如果不借助其他腳手架模板,瀏覽器端的代碼(JavaScript/CSS/Views)只能手動添加。

2.2 優(yōu)酷 - PHP中間層框架

優(yōu)酷的PHP中間層框架并未開源,所以就粗略的介紹一下吧。

中間層框架不涉及Model層,不涉及數(shù)據(jù)庫操作,只包括Controller和View層。這個(gè)框架的理念是:任何一個(gè)模塊都被視為一個(gè)webapp,每個(gè)webapp都是一個(gè)SPA,比如登錄/注冊模塊Passport、訂閱模塊Subscribe等。腳手架只能創(chuàng)建一種文件類型:一個(gè)完整的webapp。其中包括Controller文件、Resource文件(瀏覽器層)和路由配置文件。

由于每個(gè)模塊webapp都是一個(gè)SPA,包含一個(gè)Controller文件,一個(gè)view入口文件、一個(gè)入口js文件和一個(gè)css文件,所以腳手架創(chuàng)建的初始文件就已經(jīng)夠用了,開發(fā)者只需要手動添加子模塊文件即可。同時(shí),技術(shù)棧統(tǒng)一,build功能封裝完備,不需要額外配置。這種形態(tài)的腳手架基本滿足了優(yōu)酷PHP中間層框架的需求。

2.3 yeoman - 可能是最好的開源腳手架框架

提起腳手架這三個(gè)字就不得不提yeoman這名老將。Yeoman在2012年Google I/O上首次發(fā)布,至今已經(jīng)5年的光景了。對于前端技術(shù)圈子來說,5年的時(shí)間可以讓絕大部分的技術(shù)遭到淘汰,而yeoman堅(jiān)持到了今天,且扔未現(xiàn)衰退之勢。我們可以短暫回顧一下5年前的前端技術(shù),你可能會想到Knockout和Backbone,也可能會想到Y(jié)UI 3,甚至可能會想起被ExtJS所支配的恐怖。然后再看看這些在當(dāng)時(shí)熱火朝天的技術(shù)目前的市場狀態(tài),是否都已是昨日黃花垂垂老矣?而yeoman之所以能“活”這么久,得益于它明確的定位。

yeoman的slogan是“THE WEB'S SCAFFOLDING TOOL FOR MODERN WEBAPPS”-腳手架工具,但我個(gè)人認(rèn)為稱之為腳手架框架更為合適。yeoman不能直接創(chuàng)建項(xiàng)目文件,它提供了一套完整的開發(fā)腳手架API,你可以通過這些API定制符合自己業(yè)務(wù)需求的任意的腳手架方案。換句話說,yeoman不封裝任何方案,它是完全開放、高度可擴(kuò)展的。

yeoman的API具備了前文所列出的腳手架需要具備的所有要素,如果你需要開發(fā)一個(gè)屬于自己的腳手架,yeoman是最好的選擇。后續(xù)的博文會詳細(xì)介紹如何使用yeoman提供的Node.js API將其集成到工程化框架中。

3. 總結(jié)

雖然前端腳手架沒有固定形態(tài),但是有必須具備的要素。從功能實(shí)現(xiàn)的角度,要考慮與業(yè)務(wù)的高度匹配;從底層框架的角度,要具備高度的可擴(kuò)展性和執(zhí)行環(huán)境多樣性支持。

這可能是目前針對前端腳手架理念說的廢話最多的一篇文章了,哈哈。所述內(nèi)容都是筆者的一些淺薄的心得,希望能夠給大家一些啟發(fā)。

PS:做了一個(gè)簡單地視頻分享,大家可以使用微信掃描二維碼觀看。
Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

http://www.cnblogs.com/ihardcoder/p/6648423.html