原文標題:Gulp for Beginners
作者: Zell Liew
翻譯:治電小白菜
原文地址:https://css-tricks.com/gulp-for-beginners/
原文代碼:https://github.com/zellwk/gulp-starter-csstricks
譯者注:發(fā)現(xiàn)這篇文章很棒,所以就翻譯了,能力有限,有錯誤可以指出。
我的學(xué)習代碼https://github.com/klren0312/gulp_begin
如果覺得npm很慢可以使用cnpm。
Gulp是一個在你開發(fā)web時,幫助你完成幾個任務(wù)的工具。它經(jīng)常用來進行一些前端任務(wù),比如:
- 生成一個Web服務(wù)器
- 當一個文件保存時,瀏覽器自動刷新
- 編譯像Sass或者LESS一樣的預(yù)處理器
- 優(yōu)化資源文件,像CSS,JavaScript和圖片等
這些并不是Gulp的全部功能。如果你足夠瘋狂,你甚至可以使用Gulp創(chuàng)造一個靜態(tài)頁面生成器(我已經(jīng)做到了!)。所以,Gulp是非常強大的,但是如果你想創(chuàng)建你自己的構(gòu)建流程,你就要去學(xué)習如何使用Gulp。
所以這就是這篇文章所要做的。它將幫助你入門Gulp,你就可以自己探索其他任何東西。
在我們投入Gulp的學(xué)習之前,讓我們來討論一下,為什么你可能希望使用Gulp,而不是其他相似的工具。
為什么選擇Gulp?
類似Gulp的工具通常被人稱作“構(gòu)建工具”,因為它們是運行任務(wù)來構(gòu)建網(wǎng)頁的工具。兩個最流行的構(gòu)建工具是Gulp和Grunt(Chris 有一篇文章關(guān)于學(xué)習Grunt)。但是這兒還有其他工具,broccoli聚焦于資源文件的編譯,是一個最常見的構(gòu)建工具之一。
這兒已經(jīng)有大量文章覆蓋Grunt和Gulp的區(qū)別以及為什么你可能使用其中一個。如果你想了解更多,你可以查看這篇文章,這一篇,或者這篇。brunch式一個相似的工具,聚焦于資源文件以及它捆綁在一些常用的任務(wù)上,像服務(wù)器和文件監(jiān)視器。
最主要的區(qū)別是你如何使用他們配置工作流。Gulp配置傾向于更短和更簡單,相對于Grunt。Gulp也傾向于運行更快。
現(xiàn)在讓我們繼續(xù)向前,以及學(xué)習如何使用Gulp配置一個工作流
我們要配置什么
在看完這篇文章后,你將擁有一個工作流,來進行我們文章開始所說的一些任務(wù):
- 生成一個Web服務(wù)器
- 當一個文件保存時,瀏覽器自動刷新
- 編譯像Sass或者LESS一樣的預(yù)處理器
- 優(yōu)化資源文件,像CSS,JavaScript和圖片等
你也將學(xué)習如何使用容易理解和執(zhí)行的命令行,將不同的任務(wù)捆綁在一起。
讓我們開始在你的電腦上安裝Gulp吧。
安裝Gulp
在你安裝Gulp之前,需要安裝Node.js(Node)環(huán)境。
如果你沒有安裝,你可以在這個網(wǎng)頁來獲取安裝包。
當你安裝好Node后,你可以通過使用下列命令行來安裝Gulp。
$sudo npm install gulp -g
提示:只有Mac用戶需要sudo(看Pawel Grzybek的評論,如果你不想使用sudo)。上面的“$"只是代表命令行,沒有特殊意義。
npm install命令,使用Node Package Manager(npm)來安裝Gulp。
-g標志代表這個安裝時全局安裝到你的電腦上,這就運行你在電腦的任何地方都能使用gulp。
Mac用戶需要額外的sudo,因為他們需要管理員權(quán)限來全局安裝Gulp。
現(xiàn)在你已經(jīng)安裝好了Gulp,讓我們使用Gulp來創(chuàng)建一個項目吧。
創(chuàng)建一個Gulp項目
第一步,本次教程,我們要創(chuàng)建一個叫project文件夾作為我們的根目錄。在目錄里運行npm init命令行來初始化項目。
npm init命令行創(chuàng)建一個package.json文件,用來保存關(guān)于項目的信息,比如一些在項目中使用的依賴(Gulp就是一個依賴)。
npm init將提示你:

一旦package.json文件創(chuàng)建后,我們可以使用下面命令行,在項目中安裝Gulp
$npm install gulp --save-dev
這時候,我們就將Gulp安裝到項目里了,而不是全局安裝,這就是為什么命令行有些不一樣。
你將會看到在這里不需要sudo,因為我們沒有全局安裝Gulp,所以-g也是不需要的。我們增加--save-dev,來告訴計算機增加gulp到package.json到dev依賴。

如果你查看項目文件夾,在命令執(zhí)行結(jié)束,你應(yīng)該能看到Gulp在node_modules文件夾里。

我們差不多可以開始使用Gulp來工作了,在我們做這個之前,我們還要了解我們?nèi)绾卧陧椖恐惺褂肎ulp,以及確定項目的目錄結(jié)構(gòu)。
決定項目文件夾結(jié)構(gòu)
Gulp對于很多文件夾結(jié)構(gòu)都可以足夠靈活的使用。在對項目結(jié)構(gòu)進行調(diào)整之前,你只需要理解內(nèi)部工作原理。
對于這篇文章,我們將使用以下結(jié)構(gòu)來構(gòu)建項目:
|- app/
-----|- css/
-----|- fonts/
-----|- images/
-----|- index.html
-----|- js/
-----|- scss/
|- dist/
|- gulpfile.js
|- node_modules/
|- package.json
在這個結(jié)構(gòu)里,我們將使用app文件夾用于開發(fā)目的,當dist文件夾內(nèi)包括了優(yōu)化后的文件,用于生產(chǎn)時候的頁面。
自從app被用來開發(fā)目的后,我們所有的代碼都要放到app文件夾中。
我們將不得不保持目錄結(jié)構(gòu)當我們運行我們的Glup配置。現(xiàn)在,讓我們開始在gulpfile.js中,創(chuàng)建我們第一個Gulp任務(wù)。
編寫你的第一個Gulp任務(wù)
第一步是在gulpfile中requireGulp
var gulp = require('gulp');
這個require聲明告訴Node在node_modules中尋找名為gulp的包。一旦包被找到,我們就將它里面內(nèi)容賦值到變量gulp中。
我們現(xiàn)在可以開始使用gulp變量寫一個gulp任務(wù)。一個gulp任務(wù)的基本語法是:
gulp.task('task-name',function(){
//stuff here
})
task-name指的是任務(wù)的名稱,當你在Gulp中運行這個任務(wù)時,將會使用這個名稱。你也可以在命令行中運行相同的任務(wù),通過gulp task-name
為了測試它,讓我們創(chuàng)建一個hello任務(wù),來說Hello Zell!
gulp.task('hello', function(){
console.log('Hello Zell!');
});
我們可以在命令行中通過gulp hello來運行這個任務(wù)
$gulp hello
命令行將會返回一個日志,打印出Hello Zell!

Gulp任務(wù)通常要比這個復(fù)雜一點。它通常包括兩個附加的Gulp時間,加上各種各樣的Gulp插件。
這兒是一個真實任務(wù)的樣子
gulp.task('task-name',function(){
return gulp.src('source-files')
.pipe(aGulpPlugin())
.pipe(gulp.dest('destination'))
});
正如你能看到的,一個真實的任務(wù)有兩個額外的事件gulp.src'和gulp.dest。gulp.src告訴Gulp任務(wù),所要使用的文件。gulp.dest`告知當任務(wù)完成后,Gulp輸出文件的地址。
讓我們來嘗試構(gòu)造一個真實的任務(wù),將Sass文件編譯成CSS文件。
Gulp預(yù)處理
在Gulp中,我們可以將Sass編譯成CSS,使用一個叫做gulp-sass的插件。你可以安裝gulp-sass到你的項目中,通過使用以下命令
$ npm install gulp-sass --save-dev
在我們使用插件之前,我們需要從node_moudles文件夾中require gulp-sass,就像我們引入gulp一樣
var gulp = require('gulp');
// Requires the gulp-sass plugin
var sass = require('gulp-sass');
我們可以使用gulp-sass通過將aGulpPlugin()替換成sass(),因為任務(wù)用來將Sass編譯成CSS,所以讓我們將他命名為'sass'
gulp.task('sass', function(){
return gulp.src('source-files')
.pipe(sass())
.pipe(gulp.dest('destination'));
});
我們需要提供給sass任務(wù)原始文件以及目標路徑,來使任務(wù)工作。所以讓我們在app/scss文件夾中創(chuàng)建一個styles.scss文件。這個文件將會被加入到sass任務(wù)中的gulp.src中。
我們想輸出最后的styles.css文件到app/css文件夾,我們就要將其加入到gulp.dest的destination處。
gulp.task('sass',function(){
return gulp.src('app/scss/styles.scss')
.pipe(sass())
.pipe(gulp.dest('app/css'))
})
我們想測試sass任務(wù)是否能像我們預(yù)想的工作。我們可以在styules.scss中增加一個Sass函數(shù)
.testing{
width:percentage(5/7;
}
如果你在命令行中運行gulp sass,你應(yīng)該就能看到app/css中會有一個styles.css文件被創(chuàng)建。此外,它代碼中的percentage(5/7)被計算出來了71.42857%
/* styles.css */
.testing{
width: 71.42857%;
}
我們知道了sass任務(wù)是如何工作。
有時我們需要能夠編譯多個.scss文件成CSS文件。我們可以在Node globs的幫助下完成(globs參數(shù)是文件匹配模式,類似正則表達式,用來匹配文件路徑包括文件名)。
供參考:Gulp-sass使用LibSass來將Sass轉(zhuǎn)換成CSS。這比基于Ruby的方法要快。如果你希望Ruby方法,你也可以使用gulp-ruby-sass或者gulp-compass插件來代替。
Node的Globbing
Globs是匹配文件模式,允許你在gulp.src中增加多個文件。它就像正則表達式一樣,但是只用來表示文件路徑。
當你使用glob,計算機檢查文件名和路徑以特定的特征。如果特征存在,文件就會被匹配。
大部分Gulp工作流傾向于只要求4個不同的匹配模式。
1.*.scss:*特征是一個通配符,用來匹配當前路徑中的一些特征文件。倘若這樣,我們將匹配根路徑下,所有以.scss為后綴名的文件
2.**/*.scss:這是一個更極端版本的*特征,匹配在根路徑和一些子路徑的以.scss結(jié)尾的文件
3.!not-me.scss:!表明,Gulp應(yīng)該排除這個匹配的特征,當你要在匹配的文件中,排除一個文件,是非常有用的。倘若這樣,not-me.scss將被排除出匹配。
4.*.+(scss|sass):加號+和括號()``允許Gulp匹配大量的特征,不同的特征使用|分隔開。倘若這樣,Gulp將匹配根目錄下所有以.scss或者.sass`結(jié)尾的文件。
在我們現(xiàn)在知道glob之后,我們可以將app/scss/styles.scss替換成scss/**/*.scss,這樣可以匹配app/scss或者子路徑下的.scss文件。
gulp.task('sass', function(){
return gulp.src('app/scss/**/*.scss)
.pipe(sass())
.pipe(gulp.dest('app/css'))
})
其他在app/scss文件夾下找到的Sass文件,將自動被包括到sass任務(wù)中。如果你增加一個print.scss文件到項目中,你將看到print.css被創(chuàng)建到app/css。

我們現(xiàn)在可以通過一個命令,管理所有Sass文件編譯成CSS文件。但是問題是,有什么可以讓我們不用每次都手動運行gulp sass,將Sass編譯成CSS?
監(jiān)視Sass文件更改
Gulp提供我們一個watch方法,監(jiān)視是否有文件更改。watch文件的語法是:
//Gulp watch syntax
gulp.watch('files-to-watch',['tasks','to','run']);
如果我們希望監(jiān)視多個Sass文件以及運行sass任務(wù),當一個Sass文件被保存,我們只要將files-to-watch替換成app/scss/**/*.scss,將['task','to','run']替換成[sass]:
//Gulp watch syntax
gulp.watch('app/scss/**/*.scss',['sass']);
雖然更多時候,我們希望同時監(jiān)視多種類型文件。為了實現(xiàn),我們可以將多個監(jiān)視進程加入到一個組里,放到一個watch任務(wù):
gulp.task('watch',function(){
gulp.watch('app/scss/**/*.scss',['sass']);
//other watchers
});
如果你在命令行中運行gulp watch,你將立即看到看Gulp的監(jiān)視。

它將自動運行sass任務(wù),當你保存一個.scss文件。

讓我們來進行下一步,以及讓Gulp重新加載瀏覽器,當我們保存一個.scss文件,通過Browser Sync。
Browser Sync的實時加載
Browser Sync使開發(fā)Web更加容易,通過創(chuàng)建一個Web服務(wù)器,幫助我們更容易的實時加載。它有其他的特性,比如跨多設(shè)備同步操作。
我們首先要安裝Browser Sync:
$ npm install browser-sync --save-dev
你或許會注意到,當我們安裝Browser Sync時,沒有gulp-前綴。這是因為Browser Sync與Gulp兼容,所以我們不需要用到插件。
要使用Browser Sync,我們要requireBrowser Sync
var browserSync = require('browser-sync').create();
我們需要創(chuàng)建一個browserSync任務(wù),讓Gulp生成一個服務(wù)器用于Browser Sync。因此我們運行一個服務(wù)器,我們需要讓Browser Sync 知道服務(wù)器的根目錄。在我們的例子中,就是app文件夾:
gulp.task('browserSync',function(){
browserSync.init({
server: {
baseDir:'app'
},
})
})
我們也需要稍微改變我們的sass任務(wù),讓Browser Sync能夠注入新的CSS樣式(更新CSS)到瀏覽器,當sass任務(wù)運行時。
gulp.task('sass',function(){
return gulp.src('app/scss/**/*.scss')
.pipe(sass())
.pipe(gulp.dest('app/css'))
.pipe(browserSync.reload({
stream: true
}))
});
我們已經(jīng)配置好了Browser Sync。現(xiàn)在,我們需要同時運行watch和browserSync任務(wù)來進行實時加載。
這個將要笨重的打開兩個命令行窗口以及獨立運行gulp browserSync和gulp watch,所以,讓我們使用Gulp來讓他們一起運行,通過告知watch任務(wù),browserSync必須在watch之前完成后,watch才能運行。
我們能做到,通過給watch任務(wù)添加第二參數(shù)。語法如下:
gulp.task('watch', ['array', 'of', 'tasks', 'to', 'complete','before', 'watch'], function (){
// ...
})
在這種情況下,我們添加了browserSync任務(wù)。
gulp.task('watch',['browserSync'],function(){
gulp.watch('apjp/scss/**/*.scss',['sass']);
//other watchers
})
我們也希望確定sass在watch之前運行,所以CSS將在我們運行Gulp命令時,是最新的。
gulp.task('watch',['browserSync','sass'],function(){
gulp.watch('app/scss/**/*.scss',['sass']);
// other watchers
});
現(xiàn)在,如果你在命令行中運行gulp watch,Gulp會同時開啟sass和browserSync任務(wù)。當兩個任務(wù)都完成后,watch將會運行。

同時,一個顯示app/index.html文件的瀏覽器窗口也將突然彈出。如果你改變了styles.scss文件,你將會看到瀏覽器自動刷新效果。

在我們結(jié)束這個實時更新小節(jié)之前,還有一個件事情。既然我們已經(jīng)監(jiān)視了.scss文件,并重新加載,為什么不更進一步,當HTML文件和JavaScript文件保存后,重新加載瀏覽器呢?
我們可以通過增加兩個監(jiān)視進程,以及當一個文件保存后,喚起browserSync.reload函數(shù)。
gulp.task('watch',['browserSync','sass'], function(){
gulp.watch('app/scss/**/*.scss',['sass']);
//Reloads the browser whenever HTML or JS files changes
gulp.watch('app/*.html',browserSync.reload);
gulp.watch('app/js/**/*.js', browserSync.reload);
});
到目前為止,在這個教程中,我們已經(jīng)處理了三件事:
1.創(chuàng)建一個開發(fā)用的WEB服務(wù)器
2.使用Sass編譯器
3.當文件改變后,自動重新加載瀏覽器
讓我們進入下一屆,討論優(yōu)化資源文件的部分。我們將從優(yōu)化CSS和JavaScript文件開始。
優(yōu)化CSS和JavaScript文件
當我們嘗試優(yōu)化CSS和JavaScript文件給生產(chǎn)使用,開發(fā)者有兩個任務(wù)來執(zhí)行:壓縮和串聯(lián)。
開發(fā)者面對一個問題是,當自動化運行這個進程時,很難將你的腳本串聯(lián)成正確的順序。
比如說我們在index.html有三個腳本標簽
<body>
<script src="js/lib/a-library.js"></script>
<script src="js/lib/another-library.js"></script>
<script src="js/main.js"></script>
</body>
這些腳本在兩個不同的路徑。這將很難使用傳統(tǒng)的插件(比如gulp-concatenate)來鏈接他們。
很感激,這兒有一個有用的Gulp插件,gulp-useref解決了這個問題。
Gulp-useref 連接一定數(shù)量的CSS和JavaScript文件在一個單獨的文件里,通過尋找一個注釋,以“”.他的語法是:
<!-- build:<type> <path> -->
<!-- endbuild -->
<type>可以為js,css 或者remove。最好設(shè)置type為你試圖連接的文件的類型。如果你設(shè)置type為remove,Gulp將移除整個構(gòu)件塊,而不生成文件。
<path>指的是生成文件的目標地址。
我們希望最終生成的js文件在js文件夾,名為main.min.js.因此標記應(yīng)為:
<!-- build:js js/main.min.js -->
<script src="js/lib/a-library.js"></script>
<script src="js/lib/another-library.js"></script>
<script src="js/main.js"></script>
<!-- endbuild -->
現(xiàn)在讓我們在gulpfile中配置gulp-useref插件。我們將安裝這個插件,然后在gulpfile中引入它。
$ npm install gulp-useref --save-def
var useref = require('gulp-useref');
設(shè)置useref任務(wù)和我們到目前為止設(shè)置的其他任務(wù)相似。這兒是代碼:
gulp.task('useref',function(){
return gulp.src('app/*.html')
.pipe(useref())
.pipe(gulp.dest('dist'))
});
現(xiàn)在如果你運行這個useref任務(wù),Gulp將貫穿三個腳本標簽,以及連接他們到dist/js/main.min.js.

但是這個文件現(xiàn)在并沒有被壓縮。我們將使用gulp-uglify插件,來壓縮JavaScript文件。我們也需要另一個插件,叫gulp-if,但是我們只能試圖去壓縮JavaScript文件。
$ npm install gulp-uglify --save-dev
var uglify = require('gulp-uglify');
var gulpIf = require('gulp-if');
gulp.task('useref', function(){
return gulp.src('app/*.html')
.pipe(useref())
.pipe(gulpIf('*.js',uglify()))
.pipe(gulp.dest('dist')
});
Gulp現(xiàn)在應(yīng)該自動壓縮main.min.js文件,當你運行useref任務(wù)。
還有一件有關(guān)Gulp-useref的使沒有透露,就是它自動改變所有在 ""中的標簽成'js/main.min.js'.

很棒是不是!
我們可以使用相同的方法來連接CSS文件(如果你打算增加多個)。我們將遵循相同的進程以及增加一個build注釋。
<!--build:css css/styles.min.css-->
<link rel="stylesheet" href="css/styles.css">
<link rel="stylesheet" href="css/another-stylesheet.css">
<!--endbuild-->
我們也要壓縮連接后的CSS文件。我們需要使用一個叫做gulp-cssnano的插件來幫助我們壓縮。
$ npm install gulp-cssnano
var cssnano = require('gulp-cssnano');
gulp.task('useref',function(){
return gulp.src('app/*.html')
.pipe(useref())
.pipe(gulpIf('*.js',uglify()))
.pipe(gulpIf('*.css',cssnano()))
.pipe(gulp.dest('dist'))
});
現(xiàn)在當你運行useref任務(wù),你將得到一個優(yōu)化后的CSS文件以及一個優(yōu)化后的JavaScript文件。
讓我們繼續(xù)來優(yōu)化圖片。
優(yōu)化圖片
你可能已經(jīng)猜到了;我們需要使用gulp-imagemin來幫助我們壓縮圖片。
$ npm install gulp-imagemin --save-dev
var imagemin = require('gulp-imagemin');
通過gulp-imagemin的幫助,我們能壓縮png,jpg,gif甚至使svg。讓我們創(chuàng)建一個images任務(wù)來完成這個壓縮進程。
gulp.task('images',function(){
return gulp.src('app/images/**/*.+(png|jpg|gif|svg)')
.pipe(imagemin())
.pipe(gulp.dest('dist/iamges'))
}
由于不同文件類型要使用不同的方式壓縮,你或許要在imagemin中增加選項,來自定義如何壓縮文件。
比如你可以通過設(shè)置interlaced選項為true,來創(chuàng)建 interlacedGIFs
gulp.task('images', function(){
return gulp.src('app/images/**/*.+(png|jpg|jpeg|gif|svg)')
.pipe(imagemin({
// Setting interlaced to true
interlaced: true
}))
.pipe(gulp.dest('dist/images'))
});
你可以玩玩其他選項,如果你希望的話。
壓縮圖片,是一個極其緩慢的進程,除非必要,你是不會想重復(fù)的。為了做好這個,我們可以使用gulp-cache插件。
$ npm install gulp-cache --save-dev
var cache = require('gulp-cache');
gulp.task('images', function(){
return gulp.src('app/images/**/*.+(png|jpg|jpeg|gif|svg)')
// Caching images that ran through imagemin
.pipe(cache(imagemin({
interlaced: true
})))
.pipe(gulp.dest('dist/images'))
});
我們幾乎完成了優(yōu)化進程。這兒有多個文件夾,我們需要從app文件夾編譯到dist文件夾中,比如字體文件夾。讓我們來做這件事。
將字體文件夾賦值到Dist文件夾
由于字體文件已經(jīng)壓縮了,所以我們不需要做額外的事。我們需要做的就是將字體復(fù)制到dist。
我們可以使用Gulp復(fù)制文件通過gulp.src和gulp.dest,不需要其他插件。
gulp.task('fonts', function() {
return gulp.src('app/fonts/**/*')
.pipe(gulp.dest('dist/fonts'))
})
現(xiàn)在當你運行gulp fonts,Gulp將會復(fù)制字體文件到dist中。

現(xiàn)在我們有六個不同的任務(wù)在gulpfile中,以及他們每個都需要單獨調(diào)用一個命令行,這是有點麻煩的,所以我們希望把所有都放到一個命令中。
在我們做那個之前,讓我們來看看如何自動清理生成的文件。
自動清理生成的文件
由于我們自動生成文件,我們希望確定那些不再使用的文件不保留在我們不知道的地方。
這個進程被叫做清理(或者用更簡單的術(shù)語來說,刪除文件)
我們將使用del幫助我們完成清理。
$ npm install del --save-dev
var del = require('del');
del函數(shù)接受一組node globs數(shù)組,告知那些文件夾需要刪除。
在Gulp任務(wù)中設(shè)置它就和我們第一個“hello”的示例一樣。
gulp.task('clean:dist',function(){
return del.sync('dist');
})
現(xiàn)在當你運行gulp clean:dist時,Gulp將刪除dist文件夾。
提示:我們不必擔心刪除dist/images文件夾。因為gulp-cache已經(jīng)存儲了圖片的緩存在你本地系統(tǒng)里。
要在你本地系統(tǒng)中刪除緩存,你要創(chuàng)建一個單獨的任務(wù),叫做cache:clear
gulp.task('cache:clear',function(callback){
return cache.clearAll(callback)
})
Phew, that's a mouthful(真繞口?)?,F(xiàn)在讓我們把所有任務(wù)都組合到一起吧。
組合Gulp任務(wù)
讓我們總結(jié)一下我們做的吧。到目前為止,我們創(chuàng)建了兩個不同Gulp任務(wù)集。
第一個任務(wù)集是一個開發(fā)進程,我們可以用它編譯Sass到CSS,監(jiān)視文件的修改,從而重新加載瀏覽器。
第二個任務(wù)集是壓縮進程,我們?yōu)樯a(chǎn)網(wǎng)站準備了所有文件。我們壓縮資源文件,像CSS,JavaScript和圖片在這個進程以及從app文件夾復(fù)制字體文件到dist文件夾。
我們已經(jīng)將第一個任務(wù)集集合到一個簡單的工作流,通過gulp watch命令:
gulp.task('watch',['browserSync','sass'], function(){
//...watchers
})
第二個任務(wù)集包括我們需要運行來生成生產(chǎn)用的網(wǎng)頁的任務(wù)。這包括了clean:dist,sass,useref,images和fonts。
如果我們有同樣的思路,我們能創(chuàng)建一個build任務(wù)來聯(lián)系所有。
gulp.task('build', ['clean:dist','sass','useref','images','fonts'], function(){
console.log('building files');
})
不幸的是,我們這樣構(gòu)建build任務(wù),因為這樣會導(dǎo)致Gulp將第二個參數(shù)全部同時運行。
這可能會使useref,images或者甚至fonts在clean之前運行完成,這就意味著,最后整個dist文件夾被刪除。
所以要確定刪除任務(wù)要在所有任務(wù)之前完成,我們需要使用一個額外的插件,叫做Run Sequence。
$ npm install run-sequence --save-dev
這是一個使用run-sequence的任務(wù)隊列的語法:
var runSequence = require('run-sequence');
gulp.task('task-name',function(callback){
runSequence('task-one','task-two','task-three',callback);
});
當task-name被喚起,Gulp將先運行task-one.當task-one結(jié)束后,Gulp將自動啟動task-two.最后當task-two完成后,Gulp將運行task-three
Run Requence 也允許你同時運行任務(wù),如果你把他們放在一個數(shù)組里:
gulp.task('task-name',function(callback){
runSequence('task-one',['tasks','two','run','in','parallel'],'task-three',callback);
})
在這種情況下,Gulp第一個運行task-one.當task-one完成后,Gulp同時運行第二個參數(shù)里每個任務(wù)。第二個參數(shù)中所有任務(wù)運行完成后,task-three才能運行。
所以我們現(xiàn)在能創(chuàng)建一個任務(wù),確定clean:dist第一個運行,然后其他任務(wù)運行:
gulp.task('build',function(callback){
runSequence('clean:dist',['sass','useref','images','fonts'],
callback
);
});
為了保持事情的一致性,我們也構(gòu)建相同的隊列在第一組。讓我們使用default作為任務(wù)名:
gulp.task('default',function(callback){
runSequence(['sass','browserSync','watch'],
callback
);
})
為什么用default?因為當你有個任務(wù)叫default,你就可以很簡單的使用gulp命令運行,會省去鍵盤的敲擊次數(shù)。。。
最后這里是一個Github repo,里面都是我們所做的工作。
結(jié)束
我們已經(jīng)經(jīng)過了Gulp的基礎(chǔ)以及創(chuàng)建了一個工作流,可以將Sass編譯成CSS,同時監(jiān)測HTML和JS文件發(fā)生改變。我們可以在命令行通過gulp命令運行這個任務(wù)。
我們也構(gòu)建了第二個任務(wù),build,創(chuàng)建一個dist文件夾給生產(chǎn)用網(wǎng)頁。我們編譯Sass為CSS,壓縮我們所有的資源文件以及復(fù)制必要的文件夾到dist文件夾。我們可以在命令行中運行gulp build來運行這個任務(wù)。
最后,我們有一個clean 任務(wù),用來清理生成的dist文件夾和一些創(chuàng)建的圖片緩存,允許我們移除一些沒注意的留在dist文件夾里的舊的文件。
我們已經(jīng)創(chuàng)建了一個強健的工作流,到目前為止,這個已經(jīng)有足夠能力來進行大多數(shù)WEB開發(fā)。這兒有一些Gulp和工作流,你可以探索來是這個進程更加完美。這里有一些資源:
For development:
- Using Autoprefixer to write vendor-free CSS code
- Adding Sourcemaps for easier debugging
- Creating Sprites with sprity
- Compiling only files that have changed with gulp-changed
- Writing ES6 with Babel or Traceur
- Modularizing Javascript files with Browserify, webpack, or jspm
- Modularizing HTML with template engines like Handlebars or Swig
- Splitting the gulpfile into smaller files with require-dir
- Generating a Modernizr script automatically with gulp-modernizr
For optimization:
- Removing unused CSS with unCSS
- Further optimizing CSS with CSSO
- Generating inline CSS for performance with Critical