gulp

編輯于2015年 轉(zhuǎn)載自某作者的譯文 作者要是看到請(qǐng)聯(lián)系我注明出處

對(duì)網(wǎng)站資源進(jìn)行優(yōu)化簸喂,并使用不同瀏覽器測(cè)試并不是網(wǎng)站設(shè)計(jì)過(guò)程中最有意思的部分,但是這個(gè)過(guò)程中的很多重復(fù)的任務(wù)能夠使用正確的工具自動(dòng)完成,從而使效率大大提高,這是讓很多開(kāi)發(fā)者覺(jué)得有趣的地方。
Gulp是一個(gè)構(gòu)建系統(tǒng),它能通過(guò)自動(dòng)執(zhí)行常見(jiàn)任務(wù)爆安,比如編譯預(yù)處理CSS,壓縮JavaScript和刷新瀏覽器仔引,來(lái)改進(jìn)網(wǎng)站開(kāi)發(fā)的過(guò)程扔仓。通過(guò)本文褐奥,我們將知道如何使用Gulp來(lái)改變開(kāi)發(fā)流程,從而使開(kāi)發(fā)更加快速高效翘簇。
What Is Gulp?
Gulp是一個(gè)構(gòu)建系統(tǒng)撬码,開(kāi)發(fā)者可以使用它在網(wǎng)站開(kāi)發(fā)過(guò)程中自動(dòng)執(zhí)行常見(jiàn)任務(wù)。Gulp是基于Node.js構(gòu)建的版保,因此Gulp源文件和你用來(lái)定義任務(wù)的Gulp文件都被寫進(jìn)了JavaScript(或者CoffeeScript)里呜笑。前端開(kāi)發(fā)工程師還可以用自己熟悉的語(yǔ)言來(lái)編寫任務(wù)去lint JavaScript和CSS、解析模板以及在文件變動(dòng)時(shí)編譯LESS文件(當(dāng)然這些只是一小部分例子)彻犁。
Gulp本身雖然不能完成很多任務(wù)叫胁,但它有大量插件可用,開(kāi)發(fā)者可以訪問(wèn)插件頁(yè)面或者在npm搜索gulpplugin就能看到汞幢。例如驼鹅,有些插件可以用來(lái)執(zhí)行JSHint編譯CoffeeScript森篷,執(zhí)行Mocha測(cè)試谤民,甚至更新版本號(hào)
對(duì)比其他構(gòu)建工具疾宏,比如Grunt,以及最近流行的Broccoli触创,我相信Gulp會(huì)更勝一籌(請(qǐng)看后面的”Why Gulp?”部分)坎藐,同時(shí)我匯總了一個(gè)使用Javascript編寫的構(gòu)建工具清單,可供大家參考哼绑。
Gulp是一個(gè)可以在GitHub上找到的開(kāi)源項(xiàng)目岩馍。
Installing Gulp
安裝Gulp的過(guò)程十分簡(jiǎn)單。首先抖韩,需要在全局安裝Gulp包:
npm install -g gulp

然后蛀恩,在項(xiàng)目里面安裝Gulp:
npm install --save-dev gulp

Using Gulp
現(xiàn)在我們創(chuàng)建一個(gè)Gulp任務(wù)來(lái)壓縮JavaScript文件。首先創(chuàng)建一個(gè)名為gulpfile.js的文件茂浮,這是定義Gulp任務(wù)的地方双谆,它可以通過(guò)gulp命令來(lái)運(yùn)行,接著把下面的代碼放到gulpfile.js文件里面席揽。
var gulp = require('gulp'), uglify = require('gulp-uglify');gulp.task('minify', function () { gulp.src('js/app.js') .pipe(uglify()) .pipe(gulp.dest('build'))});

然后在npm里面運(yùn)行npm install -–save-dev gulp-uglify來(lái)安裝gulp-uglify顽馋,最后通過(guò)運(yùn)行g(shù)ulp minify來(lái)執(zhí)行任務(wù)。假設(shè)js目錄下有個(gè)app.js文件幌羞,那么一個(gè)新的app.js將被創(chuàng)建在編譯目錄下寸谜,它包含了js/app.js的壓縮內(nèi)容。想一想属桦,到底發(fā)生了什么熊痴?
我們只在gulpfile.js里做了一點(diǎn)事情他爸。首先,我們加載gulp和gulp-uglify模塊:
var gulp = require('gulp'), uglify = require('gulp-uglify');

然后果善,我們定義了一個(gè)叫minify的任務(wù)诊笤,它執(zhí)行時(shí)會(huì)調(diào)用函數(shù),這個(gè)函數(shù)會(huì)作為第二個(gè)參數(shù):
gulp.task('minify', function () {});

最后岭埠,也是難點(diǎn)所在盏混,我們需要定義任務(wù)應(yīng)該做什么:
gulp.src('js/app.js') .pipe(uglify()) .pipe(gulp.dest('build'))

如果你對(duì)數(shù)據(jù)流非常熟悉(其實(shí)大多數(shù)前端開(kāi)發(fā)人員并不熟悉),上面所提供的代碼對(duì)你來(lái)說(shuō)就沒(méi)有太大意義了惜论。
STREAMS
數(shù)據(jù)流能夠通過(guò)一系列的小函數(shù)來(lái)傳遞數(shù)據(jù)许赃,這些函數(shù)會(huì)對(duì)數(shù)據(jù)進(jìn)行修改,然后把修改后的數(shù)據(jù)傳遞給下一個(gè)函數(shù)馆类。
在上面的例子中混聊,gulp.src()函數(shù)用字符串匹配一個(gè)文件或者文件的編號(hào)(被稱為“glob”),然后創(chuàng)建一個(gè)對(duì)象流來(lái)代表這些文件,接著傳遞給uglify()函數(shù)乾巧,它接受文件對(duì)象之后返回有新壓縮源文件的文件對(duì)象句喜,最后那些輸出的文件被輸入gulp.dest()函數(shù),并保存下來(lái)沟于。
整個(gè)數(shù)據(jù)流動(dòng)過(guò)程如下圖所示: [圖片上傳中咳胃。。旷太。(1)]
當(dāng)只有一個(gè)任務(wù)的時(shí)候展懈,函數(shù)并不會(huì)起太大的作用。然而供璧,仔細(xì)思考下面的代碼:
gulp.task('js', function () { return gulp.src('js/*.js') .pipe(jshint()) .pipe(jshint.reporter('default')) .pipe(uglify()) .pipe(concat('app.js')) .pipe(gulp.dest('build'));});

在運(yùn)行這段程序之前存崖,你需要先安裝gulp,gulp-jshint,gulp-uglify和gulp-concat。
這個(gè)任務(wù)會(huì)讓所有的文件匹配js/.js(比如js目錄下的所有JavaScript文件)睡毒,并且執(zhí)行JSHint来惧,然后打印輸出結(jié)果,取消文件縮進(jìn)演顾,最后把他們合并起來(lái)供搀,保存為build/app.js,整個(gè)過(guò)程如下圖所示: [圖片上傳中偶房。趁曼。。(2)]
如果你對(duì)Grunt 足夠熟悉棕洋,就會(huì)注意到挡闰,Gulp和Grunt的工作方式很不一樣。Grunt不使用數(shù)據(jù)流,而是使用文件摄悯,對(duì)文件執(zhí)行單個(gè)任務(wù)然后保存到新的文件中赞季,每個(gè)任務(wù)都會(huì)重復(fù)執(zhí)行所有進(jìn)程,文件系統(tǒng)頻繁的處理任務(wù)會(huì)導(dǎo)致Grunt的運(yùn)行速度比Gulp慢奢驯。
如果想要獲取更加全面的數(shù)據(jù)流知識(shí)申钩,請(qǐng)查看“Stream Handbook”.
GULP.SRC()
gulp.src()方法輸入一個(gè)glob(比如匹配一個(gè)或多個(gè)文件的字符串)或者glob數(shù)組,然后返回一個(gè)可以傳遞給插件的數(shù)據(jù)流瘪阁。
Gulp使用node-glob來(lái)從你指定的glob里面獲取文件撒遣,這里列舉下面的例子來(lái)闡述,方便大家理解:
js/app.js 精確匹配文件
js/
.js 僅匹配js目錄下的所有后綴為.js的文件
js/*/.js 匹配js目錄及其子目錄下所有后綴為.js的文件
!js/app.js 從匹配結(jié)果中排除js/app.js管跺,這種方法在你想要匹配除了特殊文件之外的所有文件時(shí)非常管用
*.+(js|css) 匹配根目錄下所有后綴為.js或者.css的文件

此外义黎,Gulp也有很多其他的特征,但并不常用豁跑。如果你想了解更多的特征廉涕,請(qǐng)查看Minimatch文檔。
js目錄下包含了壓縮和未壓縮的JavaScript文件艇拍,現(xiàn)在我們想要?jiǎng)?chuàng)建一個(gè)任務(wù)來(lái)壓縮還沒(méi)有被壓縮的文件狐蜕,我們需要先匹配目錄下所有的JavaScript文件,然后排除后綴為.min.js的文件:
gulp.src(['js//.js', '!js//.min.js'])

DEFINING TASKS
gulp.task()函數(shù)通常會(huì)被用來(lái)定義任務(wù)卸夕。當(dāng)你定義一個(gè)簡(jiǎn)單的任務(wù)時(shí)层释,需要傳入任務(wù)名字和執(zhí)行函數(shù)兩個(gè)屬性。
gulp.task('greet', function () { console.log('Hello world!');});

執(zhí)行g(shù)ulp greet的結(jié)果就是在控制臺(tái)上打印出“Hello world”.
一個(gè)任務(wù)有時(shí)也可以是一系列任務(wù)快集。假設(shè)要定義一個(gè)任務(wù)build來(lái)執(zhí)行css湃累、js、imgs這三個(gè)任務(wù)碍讨,我們可以通過(guò)指定一個(gè)任務(wù)數(shù)組而不是函數(shù)來(lái)完成。
gulp.task('build', ['css', 'js', 'imgs']);

這些任務(wù)不是同時(shí)進(jìn)行的蒙秒,所以你不能認(rèn)為在js任務(wù)開(kāi)始的時(shí)候css任務(wù)已經(jīng)結(jié)束了勃黍,也可能還沒(méi)有結(jié)束。為了確保一個(gè)任務(wù)在另一個(gè)任務(wù)執(zhí)行前已經(jīng)結(jié)束晕讲,可以將函數(shù)和任務(wù)數(shù)組結(jié)合起來(lái)指定其依賴關(guān)系覆获。例如,定義一個(gè)css任務(wù)瓢省,在執(zhí)行前需要檢查greet任務(wù)是否已經(jīng)執(zhí)行完畢弄息,這樣做就是可行的:
gulp.task('css', ['greet'], function () { // Deal with CSS here});

現(xiàn)在,當(dāng)執(zhí)行css任務(wù)時(shí)勤婚,Gulp會(huì)先執(zhí)行g(shù)reet任務(wù)摹量,然后在它結(jié)束后再調(diào)用你定義的函數(shù)。
DEFAULT TASKS
你可以定義一個(gè)在gulp開(kāi)始運(yùn)行時(shí)候默認(rèn)執(zhí)行的任務(wù),并將這個(gè)任務(wù)命名為“default”:
gulp.task('default', function () { // Your default task});

PLUGINS
Gulp上有超過(guò)600種插件供你選擇缨称,你可以在插件頁(yè)面或者npm上搜索gulpplugin來(lái)瀏覽插件列表凝果。有些擁有“gulpfriendly”標(biāo)簽的插件,他們不能算插件睦尽,但是能在Gulp上正常運(yùn)行器净。 需要注意的是,當(dāng)直接在npm里搜索時(shí)当凡,你無(wú)法知道某一插件是否在黑名單上(你需要滾動(dòng)到插件頁(yè)面底部才能看到)山害。
大多數(shù)插件的使用都很方便,它們都配有詳細(xì)的文檔沿量,而且調(diào)用方法也相同(通過(guò)傳遞文件對(duì)象流給它)浪慌,它們通常會(huì)對(duì)這些文件進(jìn)行修改(但是有一些插件例外,比如validators)欧瘪,最后返回新的文件給下一個(gè)插件眷射。
讓我們用前面的js任務(wù)來(lái)詳細(xì)說(shuō)明一下:
var gulp = require('gulp'), jshint = require('gulp-jshint'), uglify = require('gulp-uglify'), concat = require('gulp-concat');gulp.task('js', function () { return gulp.src('js/*.js') .pipe(jshint()) .pipe(jshint.reporter('default')) .pipe(uglify()) .pipe(concat('app.js')) .pipe(gulp.dest('build'));});

這里使用了三個(gè)插件,gulp-jshint,gulp-uglifygulp-concat佛掖。開(kāi)發(fā)者可以參考插件的README文檔妖碉,插件有很多配置選項(xiàng),而且給定的初始值通常能滿足需求芥被。細(xì)心的讀者可能會(huì)發(fā)現(xiàn)欧宜,程序中JSHint插件執(zhí)行了2次,這是因?yàn)榈谝淮螆?zhí)行JSHint只是給文件對(duì)象附加了jshint屬性拴魄,并沒(méi)有輸出冗茸。你可以自己讀取jshint的屬性或者傳遞給默認(rèn)的JSHint的接收函數(shù)或者其他的接收函數(shù),比如jshint-stylish.
其他兩個(gè)插件的作用很清楚:uglify()函數(shù)壓縮代碼,concat(‘a(chǎn)pp.js’)函數(shù)將所有文件合并到一個(gè)叫app.js的文件中匹中。
GULP-LOAD-PLUGINS
我發(fā)現(xiàn)gulp-load-plugin模塊十分有用夏漱,它能夠自動(dòng)地從package.json中加載任意Gulp插件然后把它們附加到一個(gè)對(duì)象上。它的基本用法如下所示:
var gulpLoadPlugins = require('gulp-load-plugins'), plugins = gulpLoadPlugins();

你可以把所有代碼寫到一行顶捷,但是我并不推薦這樣做挂绰。
在執(zhí)行那些代碼之后,插件對(duì)象就已經(jīng)包含了插件服赎,并使用“駝峰式”的方式進(jìn)行命名(例如葵蒂,gulp-ruby-sass將被加載成plugins.rubySass),這樣就可以很方便地使用了重虑。例如践付,前面的js任務(wù)簡(jiǎn)化為如下:
var gulp = require('gulp'), gulpLoadPlugins = require('gulp-load-plugins'), plugins = gulpLoadPlugins();gulp.task('js', function () { return gulp.src('js/*.js') .pipe(plugins.jshint()) .pipe(plugins.jshint.reporter('default')) .pipe(plugins.uglify()) .pipe(plugins.concat('app.js')) .pipe(gulp.dest('build'));});

假設(shè)package.json文件如下面所示:
{ "devDependencies": { "gulp-concat": "~2.2.0", "gulp-uglify": "~0.2.1", "gulp-jshint": "~1.5.1", "gulp": "~3.5.6" }}

這個(gè)例子雖然已經(jīng)夠短了,但是使用更長(zhǎng)更復(fù)雜的Gulp文件會(huì)把它們簡(jiǎn)化成一兩行代碼缺厉。
三月初發(fā)布的Gulp-load-plugins0.4.0版本添加了延遲加載功能永高,提高了插件的性能隧土,因?yàn)椴寮谑褂玫臅r(shí)候才會(huì)被加載進(jìn)來(lái),你不用擔(dān)心package.json里未被使用的插件影響性能(但是你需要把他們清理掉)乏梁。換句話說(shuō)次洼,如果你在執(zhí)行任務(wù)時(shí)只需要兩個(gè)插件,那么其他不相關(guān)的插件就不會(huì)被加載遇骑。
WATCHING FILES
Gulp可以監(jiān)聽(tīng)文件的修改動(dòng)態(tài)卖毁,然后在文件被改動(dòng)的時(shí)候執(zhí)行一個(gè)或多個(gè)任務(wù)。這個(gè)特性十分有用(對(duì)我來(lái)說(shuō)落萎,這可能是Gulp中最有用的一個(gè)功能)亥啦。你可以保存LESS文件,接著Gulp會(huì)自動(dòng)把它轉(zhuǎn)換為CSS文件并更新瀏覽器练链。
使用gulp.watch()方法可以監(jiān)聽(tīng)文件翔脱,它接受一個(gè)glob或者glob數(shù)組(和gulp.src()一樣)以及一個(gè)任務(wù)數(shù)組來(lái)執(zhí)行回調(diào)。
讓我們看看下面媒鼓,build任務(wù)可以將模板轉(zhuǎn)換成html格式侥加,然后我們希望定義一個(gè)watch任務(wù)來(lái)監(jiān)聽(tīng)模板文件的變化艳狐,并將這些模板轉(zhuǎn)換成html格式。watch函數(shù)的使用方法如下所示:
gulp.task('watch', function () { gulp.watch('templates/*.tmpl.html', ['build']);});

現(xiàn)在,當(dāng)改變一個(gè)模板文件時(shí)宙搬,build任務(wù)會(huì)被執(zhí)行并生成HTML文件吱型,也可以給watch函數(shù)一個(gè)回調(diào)函數(shù)存筏,而不是一個(gè)任務(wù)數(shù)組碍岔。在這個(gè)示例中,回調(diào)函數(shù)有一個(gè)包含觸發(fā)回調(diào)函數(shù)信息的event對(duì)象:
gulp.watch('templates/*.tmpl.html', function (event) { console.log('Event type: ' + event.type); // added, changed, or deleted console.log('Event path: ' + event.path); // The path of the modified file});

Gulp.watch()的另一個(gè)非常好的特性是返回我們熟知的watcher擎厢。利用watcher來(lái)監(jiān)聽(tīng)額外的事件或者向watch中添加文件究流。例如,在執(zhí)行一系列任務(wù)和調(diào)用一個(gè)函數(shù)時(shí)动遭,你就可以在返回的watcher中添加監(jiān)聽(tīng)change事件:
var watcher = gulp.watch('templates/*.tmpl.html', ['build']);watcher.on('change', function (event) { console.log('Event type: ' + event.type); // added, changed, or deleted console.log('Event path: ' + event.path); // The path of the modified file});

除了change事件芬探,還可以監(jiān)聽(tīng)很多其他的事件:
end 在watcher結(jié)束時(shí)觸發(fā)(這意味著,在文件改變的時(shí)候厘惦,任務(wù)或者回調(diào)不會(huì)執(zhí)行)
error 在出現(xiàn)error時(shí)觸發(fā)
ready 在文件被找到并正被監(jiān)聽(tīng)時(shí)觸發(fā)
nomatch 在glob沒(méi)有匹配到任何文件時(shí)觸發(fā)

Watcher對(duì)象也包含了一些可以調(diào)用的方法:
watcher.end() 停止watcher(以便停止執(zhí)行后面的任務(wù)或者回調(diào)函數(shù))
watcher.files() 返回watcher監(jiān)聽(tīng)的文件列表
watcher.add(glob) 將與指定glob相匹配的文件添加到watcher(也接受可選的回調(diào)當(dāng)?shù)诙€(gè)參數(shù))
watcher.remove(filepath) 從watcher中移除個(gè)別文件

Reloading Changes In The Browser
當(dāng)一個(gè)文件被修改或者Gulp任務(wù)被執(zhí)行時(shí)可以用Gulp來(lái)加載或者更新網(wǎng)頁(yè)灯节。LiveReload和BrowserSync插件就可以用來(lái)實(shí)現(xiàn)在游覽器中加載更新的內(nèi)容。
LIVERELOAD
LiveReload結(jié)合了瀏覽器擴(kuò)展(包括Chrome extension)绵估,在發(fā)現(xiàn)文件被修改時(shí)會(huì)實(shí)時(shí)更新網(wǎng)頁(yè)。它可以和gulp-watch插件或者前面描述的gulp-watch()函數(shù)一起使用卡骂。下面有一個(gè)gulp-livereload倉(cāng)庫(kù)中的README文件提到的例子:
var gulp = require('gulp'), less = require('gulp-less'), livereload = require('gulp-livereload'), watch = require('gulp-watch');gulp.task('less', function() { gulp.src('less/*.less') .pipe(watch()) .pipe(less()) .pipe(gulp.dest('css')) .pipe(livereload());});

這會(huì)監(jiān)聽(tīng)到所有與less/*.less相匹配的文件的變化国裳。一旦監(jiān)測(cè)到變化,就會(huì)生成css并保存全跨,然后重新加載網(wǎng)頁(yè).
BROWSERSYNC
BroserSync在瀏覽器中展示變化的功能與LiveReload非常相似缝左,但是它有更多的功能。
當(dāng)你改變代碼的時(shí)候,BrowserSync會(huì)重新加載頁(yè)面渺杉,或者如果是css文件蛇数,會(huì)直接添加進(jìn)css中,頁(yè)面并不需要再次刷新是越。這項(xiàng)功能在網(wǎng)站是禁止刷新的時(shí)候是很有用的耳舅。假設(shè)你正在開(kāi)發(fā)單頁(yè)應(yīng)用的第4頁(yè),刷新頁(yè)面就會(huì)導(dǎo)致你回到開(kāi)始頁(yè)倚评。使用LiveReload的話浦徊,你就需要在每次改變代碼之后還需要點(diǎn)擊四次,而當(dāng)你修改CSS時(shí)天梧,插入一些變化時(shí)盔性,BrowserSync會(huì)直接將需要修改的地方添加進(jìn)CSS,就不用再點(diǎn)擊回退呢岗。


BrowserSync提供了一種在多個(gè)瀏覽器里測(cè)試網(wǎng)頁(yè)的很好方式(查看大圖)冕香。
BrowserSync也可以在不同瀏覽器之間同步點(diǎn)擊翻頁(yè)、表單操作后豫、滾動(dòng)位置悉尾。你可以在電腦和iPhone上打開(kāi)不同的瀏覽器然后進(jìn)行操作。所有設(shè)備上的鏈接將會(huì)隨之變化硬贯,當(dāng)你向下滾動(dòng)頁(yè)面時(shí)焕襟,所有設(shè)備上頁(yè)面都會(huì)向下滾動(dòng)(通常還很流暢!)饭豹。當(dāng)你在表單中輸入文本時(shí)鸵赖,每個(gè)窗口都會(huì)有輸入。當(dāng)你不想要這種行為時(shí)拄衰,也可以把這個(gè)功能關(guān)閉它褪。

BrowserSync不需要使用瀏覽器插件,因?yàn)樗旧砭涂梢越o你提供文件翘悉。(查看大圖)
BrowserSync不需要使用瀏覽器插件茫打,因?yàn)樗旧砭涂梢詾槟闾峁┪募?wù)(如果文件是動(dòng)態(tài)的,則為他們提供代理服務(wù))和用來(lái)開(kāi)啟瀏覽器和服務(wù)器之間的socket的腳本服務(wù)妖混。到目前為止這個(gè)功能的使用都十分順暢老赤。
實(shí)際上BrowserSync對(duì)于Gulp并不算一種插件,因?yàn)锽rowserSync并不像一個(gè)插件一樣操作文件制市。然而抬旺,npm上的BrowserSync模塊能在Gulp上被直接調(diào)用。
首先祥楣,需要通過(guò)npm安裝一下:
npm install --save-dev browser-sync

然后gulpfile.js會(huì)啟動(dòng)BrowserSync并監(jiān)聽(tīng)文件:
var gulp = require('gulp'), browserSync = require('browser-sync');gulp.task('browser-sync', function () { var files = [ 'app//.html', 'app/assets/css//.css', 'app/assets/imgs//.png', 'app/assets/js//.js' ]; browserSync.init(files, { server: { baseDir: './app' } });});

執(zhí)行g(shù)ulp browser-sync后會(huì)監(jiān)聽(tīng)匹配文件的變化开财,同時(shí)為app目錄提供文件服務(wù)汉柒。
此外BrowserSync的開(kāi)發(fā)者還寫了很多關(guān)于BrowserSync+Gulp倉(cāng)庫(kù)的其他用途。
Why Gulp?
前面提到過(guò)责鳍,Gulp是為數(shù)不多的使用JavaScript開(kāi)發(fā)的構(gòu)建工具之一碾褂,也有其他不是用JavaScript開(kāi)發(fā)的構(gòu)建工具,比如Rake历葛,那么我們?yōu)槭裁匆x擇Gulp呢?
目前最流行的兩種使用JavaScript開(kāi)發(fā)的構(gòu)建工具是Grunt和Gulp正塌。Grunt在2013年非常流行,因?yàn)樗鼜氐赘淖兞嗽S多人開(kāi)發(fā)網(wǎng)站的方式啃洋,它有上千種插件可供用戶使用传货,從linting、壓縮宏娄、合并代碼到使用Bower安裝程序包,啟動(dòng)Express服務(wù)都能辦到问裕。這些和Gulp的很不一樣,Gulp只有執(zhí)行單個(gè)小任務(wù)來(lái)處理文件的插件孵坚,因?yàn)槿蝿?wù)都是JavaScript(和Grunt使用的大型對(duì)象不同)粮宛,根本不需要插件,你只需用傳統(tǒng)方法啟動(dòng)一個(gè)Express服務(wù)就可以了卖宠。
Grunt任務(wù)擁有大量的配置巍杈,會(huì)引用大量你實(shí)際上并不需要的對(duì)象屬性,但是Gulp里同樣的任務(wù)也許只有幾行扛伍。讓我們看個(gè)簡(jiǎn)單的Gruntfile.js筷畦,它規(guī)定一個(gè)將LESS轉(zhuǎn)換為CSS的任務(wù),然后執(zhí)行Autoprefixer:
grunt.initConfig({ less: { development: { files: { "build/tmp/app.css": "assets/app.less" } } }, autoprefixer: { options: { browsers: ['last 2 version', 'ie 8', 'ie 9'] }, multiple_files: { expand: true, flatten: true, src: 'build/tmp/app.css', dest: 'build/' } }});grunt.loadNpmTasks('grunt-contrib-less');grunt.loadNpmTasks('grunt-autoprefixer');grunt.registerTask('css', ['less', 'autoprefixer']);

與Gulpfile.js文件進(jìn)行對(duì)比刺洒,它們執(zhí)行的任務(wù)相同:
var gulp = require('gulp'), less = require('gulp-less'), autoprefix = require('gulp-autoprefixer');gulp.task('css', function () { gulp.src('assets/app.less') .pipe(less()) .pipe(autoprefix('last 2 version', 'ie 8', 'ie 9')) .pipe(gulp.dest('build'));});

因?yàn)镚runt比Gulp更加頻繁地操作文件系統(tǒng)鳖宾,所以使用數(shù)據(jù)流的Gulp總是比Grunt快。對(duì)于一個(gè)小的LESS文件逆航,gulpfile.js通常需要6ms鼎文,而gruntfile.js則需要大概50ms——慢8倍多。這只是個(gè)簡(jiǎn)單的例子因俐,對(duì)于長(zhǎng)的文件拇惋,這個(gè)數(shù)字會(huì)增加得更顯著。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末抹剩,一起剝皮案震驚了整個(gè)濱河市撑帖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌澳眷,老刑警劉巖胡嘿,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異境蔼,居然都是意外死亡灶平,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門箍土,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)逢享,“玉大人,你說(shuō)我怎么就攤上這事吴藻÷髋溃” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵沟堡,是天一觀的道長(zhǎng)侧但。 經(jīng)常有香客問(wèn)我,道長(zhǎng)航罗,這世上最難降的妖魔是什么禀横? 我笑而不...
    開(kāi)封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮粥血,結(jié)果婚禮上柏锄,老公的妹妹穿的比我還像新娘。我一直安慰自己复亏,他們只是感情好趾娃,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著缔御,像睡著了一般抬闷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上耕突,一...
    開(kāi)封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天笤成,我揣著相機(jī)與錄音,去河邊找鬼有勾。 笑死疹启,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蔼卡。 我是一名探鬼主播喊崖,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼雇逞!你這毒婦竟也來(lái)了荤懂?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤塘砸,失蹤者是張志新(化名)和其女友劉穎节仿,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體掉蔬,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡廊宪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年矾瘾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片箭启。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡壕翩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出傅寡,到底是詐尸還是另有隱情放妈,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布荐操,位于F島的核電站芜抒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏托启。R本人自食惡果不足惜宅倒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望驾中。 院中可真熱鬧唉堪,春花似錦、人聲如沸肩民。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)持痰。三九已至灶搜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間工窍,已是汗流浹背割卖。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留患雏,地道東北人鹏溯。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像淹仑,于是被迫代替她去往敵國(guó)和親丙挽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • gulpjs是一個(gè)前端構(gòu)建工具匀借,與gruntjs相比颜阐,gulpjs無(wú)需寫一大堆繁雜的配置參數(shù),API也非常簡(jiǎn)單吓肋,學(xué)...
    依依玖玥閱讀 3,149評(píng)論 7 55
  • 對(duì)網(wǎng)站資源進(jìn)行優(yōu)化凳怨,并使用不同瀏覽器測(cè)試并不是網(wǎng)站設(shè)計(jì)過(guò)程中最有意思的部分,但是這個(gè)過(guò)程中的很多重復(fù)的任務(wù)能夠使用...
    懵逼js閱讀 1,057評(píng)論 0 8
  • 1、gulp的安裝 首先確保你已經(jīng)正確安裝了nodejs環(huán)境肤舞。然后以全局方式安裝gulp: npm install...
    F_imok閱讀 2,357評(píng)論 1 11
  • 在現(xiàn)在的前端開(kāi)發(fā)中紫新,前后端分離、模塊化開(kāi)發(fā)李剖、版本控制弊琴、文件合并與壓縮、mock數(shù)據(jù)等等一些原本后端的思想開(kāi)始...
    Charlot閱讀 5,431評(píng)論 1 32
  • gulpjs是一個(gè)前端構(gòu)建工具杖爽,與gruntjs相比,gulpjs無(wú)需寫一大堆繁雜的配置參數(shù)紫皇,API也非常簡(jiǎn)單慰安,學(xué)...
    井皮皮閱讀 1,291評(píng)論 0 10