Gulp:任務(wù)自動(dòng)管理工具

2021-09-15 16:13 更新

Gulp與Grunt一樣,也是一個(gè)自動(dòng)任務(wù)運(yùn)行器。它充分借鑒了Unix操作系統(tǒng)的管道(pipe)思想,很多人認(rèn)為,在操作上,它要比Grunt簡(jiǎn)單。

安裝

Gulp需要全局安裝,然后再在項(xiàng)目的開發(fā)目錄中安裝為本地模塊。先進(jìn)入項(xiàng)目目錄,運(yùn)行下面的命令。

npm install -g gulp

npm install --save-dev gulp

除了安裝gulp以外,不同的任務(wù)還需要安裝不同的gulp插件模塊。舉例來說,下面代碼安裝了gulp-uglify模塊。

$ npm install --save-dev gulp-uglify

gulpfile.js

項(xiàng)目根目錄中的gulpfile.js,是Gulp的配置文件。下面就是一個(gè)典型的gulpfile.js文件。

var gulp = require('gulp');
var uglify = require('gulp-uglify');

gulp.task('minify', function () {
  gulp.src('js/app.js')
    .pipe(uglify())
    .pipe(gulp.dest('build'))
});

上面代碼中,gulpfile.js加載gulp和gulp-uglify模塊之后,使用gulp模塊的task方法指定任務(wù)minify。task方法有兩個(gè)參數(shù),第一個(gè)是任務(wù)名,第二個(gè)是任務(wù)函數(shù)。在任務(wù)函數(shù)中,使用gulp模塊的src方法,指定所要處理的文件,然后使用pipe方法,將上一步的輸出轉(zhuǎn)為當(dāng)前的輸入,進(jìn)行鏈?zhǔn)教幚怼?/p>

task方法的回調(diào)函數(shù)使用了兩次pipe方法,也就是說做了兩種處理。第一種處理是使用gulp-uglify模塊,壓縮源碼;第二種處理是使用gulp模塊的dest方法,將上一步的輸出寫入本地文件,這里是build.js(代碼中省略了后綴名js)。

執(zhí)行minify任務(wù)時(shí),就在項(xiàng)目目錄中執(zhí)行下面命令就可以了。

$ gulp minify

從上面的例子中可以看到,gulp充分使用了“管道”思想,就是一個(gè)數(shù)據(jù)流(stream):src方法讀入文件產(chǎn)生數(shù)據(jù)流,dest方法將數(shù)據(jù)流寫入文件,中間是一些中間步驟,每一步都對(duì)數(shù)據(jù)流進(jìn)行一些處理。

下面是另一個(gè)數(shù)據(jù)流的例子。

gulp.task('js', function () {
  return gulp.src('js/*.js')
    .pipe(jshint())
    .pipe(uglify())
    .pipe(concat('app.js'))
    .pipe(gulp.dest('build'));
});

上面代碼使用pipe命令,分別進(jìn)行jshint、uglify、concat三步處理。

gulp模塊的方法

src()

gulp模塊的src方法,用于產(chǎn)生數(shù)據(jù)流。它的參數(shù)表示所要處理的文件,這些指定的文件會(huì)轉(zhuǎn)換成數(shù)據(jù)流。參數(shù)的寫法一般有以下幾種形式。

  • js/app.js:指定確切的文件名。
  • js/*.js:某個(gè)目錄所有后綴名為js的文件。
  • js/*/.js:某個(gè)目錄及其所有子目錄中的所有后綴名為js的文件。
  • !js/app.js:除了js/app.js以外的所有文件。
  • *.+(js|css):匹配項(xiàng)目根目錄下,所有后綴名為js或css的文件。

src方法的參數(shù)還可以是一個(gè)數(shù)組,用來指定多個(gè)成員。

gulp.src(['js/**/*.js', '!js/**/*.min.js'])

dest()

dest方法將管道的輸出寫入文件,同時(shí)將這些輸出繼續(xù)輸出,所以可以依次調(diào)用多次dest方法,將輸出寫入多個(gè)目錄。如果有目錄不存在,將會(huì)被新建。

gulp.src('./client/templates/*.jade')
  .pipe(jade())
  .pipe(gulp.dest('./build/templates'))
  .pipe(minify())
  .pipe(gulp.dest('./build/minified_templates'));

dest方法還可以接受第二個(gè)參數(shù),表示配置對(duì)象。

gulp.dest('build', {
  cwd: './app',
  mode: '0644'
})

配置對(duì)象有兩個(gè)字段。cwd字段指定寫入路徑的基準(zhǔn)目錄,默認(rèn)是當(dāng)前目錄;mode字段指定寫入文件的權(quán)限,默認(rèn)是0777。

task()

task方法用于定義具體的任務(wù)。它的第一個(gè)參數(shù)是任務(wù)名,第二個(gè)參數(shù)是任務(wù)函數(shù)。下面是一個(gè)非常簡(jiǎn)單的任務(wù)函數(shù)。

gulp.task('greet', function () {
   console.log('Hello world!');
});

task方法還可以指定按順序運(yùn)行的一組任務(wù)。

gulp.task('build', ['css', 'js', 'imgs']);

上面代碼先指定build任務(wù),它由css、js、imgs三個(gè)任務(wù)所組成,task方法會(huì)并發(fā)執(zhí)行這三個(gè)任務(wù)。注意,由于每個(gè)任務(wù)都是異步調(diào)用,所以沒有辦法保證js任務(wù)的開始運(yùn)行的時(shí)間,正是css任務(wù)運(yùn)行結(jié)束。

如果希望各個(gè)任務(wù)嚴(yán)格按次序運(yùn)行,可以把前一個(gè)任務(wù)寫成后一個(gè)任務(wù)的依賴模塊。

gulp.task('css', ['greet'], function () {
   // Deal with CSS here
});

上面代碼表明,css任務(wù)依賴greet任務(wù),所以css一定會(huì)在greet運(yùn)行完成后再運(yùn)行。

task方法的回調(diào)函數(shù),還可以接受一個(gè)函數(shù)作為參數(shù),這對(duì)執(zhí)行異步任務(wù)非常有用。

// 執(zhí)行shell命令
var exec = require('child_process').exec;
gulp.task('jekyll', function(cb) {
  // build Jekyll
  exec('jekyll build', function(err) {
    if (err) return cb(err); // return error
    cb(); // finished task
  });
});

如果一個(gè)任務(wù)的名字為default,就表明它是“默認(rèn)任務(wù)”,在命令行直接輸入gulp命令,就會(huì)運(yùn)行該任務(wù)。

gulp.task('default', function () {
  // Your default task
});

// 或者

gulp.task('default', ['styles', 'jshint', 'watch']);

執(zhí)行的時(shí)候,直接使用gulp,就會(huì)運(yùn)行styles、jshint、watch三個(gè)任務(wù)。

watch()

watch方法用于指定需要監(jiān)視的文件。一旦這些文件發(fā)生變動(dòng),就運(yùn)行指定任務(wù)。

gulp.task('watch', function () {
   gulp.watch('templates/*.tmpl.html', ['build']);
});

上面代碼指定,一旦templates目錄中的模板文件發(fā)生變化,就運(yùn)行build任務(wù)。

watch方法也可以用回調(diào)函數(shù),代替指定的任務(wù)。

gulp.watch('templates/*.tmpl.html', function (event) {
   console.log('Event type: ' + event.type);
   console.log('Event path: ' + event.path);
});

另一種寫法是watch方法所監(jiān)控的文件發(fā)生變化時(shí)(修改、增加、刪除文件),會(huì)觸發(fā)change事件??梢詫?duì)change事件指定回調(diào)函數(shù)。

var watcher = gulp.watch('templates/*.tmpl.html', ['build']);

watcher.on('change', function (event) {
   console.log('Event type: ' + event.type);
   console.log('Event path: ' + event.path);
});

除了change事件,watch方法還可能觸發(fā)以下事件。

  • end:回調(diào)函數(shù)運(yùn)行完畢時(shí)觸發(fā)。
  • error:發(fā)生錯(cuò)誤時(shí)觸發(fā)。
  • ready:當(dāng)開始監(jiān)聽文件時(shí)觸發(fā)。
  • nomatch:沒有匹配的監(jiān)聽文件時(shí)觸發(fā)。

watcher對(duì)象還包含其他一些方法。

  • watcher.end():停止watcher對(duì)象,不會(huì)再調(diào)用任務(wù)或回調(diào)函數(shù)。
  • watcher.files():返回watcher對(duì)象監(jiān)視的文件。
  • watcher.add(glob):增加所要監(jiān)視的文件,它還可以附件第二個(gè)參數(shù),表示回調(diào)函數(shù)。
  • watcher.remove(filepath):從watcher對(duì)象中移走一個(gè)監(jiān)視的文件。

gulp-load-plugins模塊

一般情況下,gulpfile.js中的模塊需要一個(gè)個(gè)加載。

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'));
});

上面代碼中,除了gulp模塊以外,還加載另外三個(gè)模塊。

這種一一加載的寫法,比較麻煩。使用gulp-load-plugins模塊,可以加載package.json文件中所有的gulp模塊。上面的代碼用gulp-load-plugins模塊改寫,就是下面這樣。

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文件包含以下內(nèi)容。

{
   "devDependencies": {
      "gulp-concat": "~2.2.0",
      "gulp-uglify": "~0.2.1",
      "gulp-jshint": "~1.5.1",
      "gulp": "~3.5.6"
   }
}

gulp-livereload模塊

gulp-livereload模塊用于自動(dòng)刷新瀏覽器,反映出源碼的最新變化。它除了模塊以外,還需要在瀏覽器中安裝插件,用來配合源碼變化。

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());
});

上面代碼監(jiān)視less文件,一旦編譯完成,就自動(dòng)刷新瀏覽器。

參考鏈接

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)