Gulp的执行顺序

正如Gulp官网的标题所说, Gulp.js -基于流的自动化构建工具. 那么问题就来了, 是什么?

流(stream)

对于一个前端来说,流的概念相对来说会比较陌生.

很多地方都把他比喻为工作线,就是你要加工一个东西,需要几道工序 ABCD, 他在工作线上按照 ABCD 的顺序加工完. 在Gulp中,流也是这样的,比如说你想要构建一个网页, 你有很多个js和很多个css文件, 需要先压缩css, 压缩js, 那就按照这个顺序来做,这一个一个的文件就在你的预想工作线中 了过去.

管道(Pipe)

任意的水流都有 水源 和 它最终会留到哪里去的目的地. 在Gulp中要搞一个 流 出来的话当然得定义要 从哪里来到哪里去. 所以 Gulp 提供了一个基本操作 pipe()

//一般的用法是
src.pipe(dst);
//src指的是从哪里来,dst指的是到哪里去.

pipe中可以是一些函数,意味着要从 src 中拿东西到 pipe() 中的 dst 处理,最终 pipe() 函数将会返回 dst,你可以将返回的 dst 作为另一个 pipe()src 以做到像流水线一样处理一道道的工序

src.pipe(a).pipe(b).pipe(c);
//程序会将 src中的文件按照 a, b, c 的顺序处理.

也就是说, pipe 中的东西会按照顺序执行

不同的来源?

假设有以下代码,一部分代码是为了压缩 js,另一部分代码是为了压缩 css

gulp.task('test', function() {
    gulp.src('src/js/*.js')
        .pipe(uglify()) //压缩js
        .pipe(gulp.dest('dist/js'));

    gulp.src('src/css/*.css')
        .pipe(cleanCSS()) //压缩css
        .pipe(gulp.dest('dist/css'));
});

上面这段代码里面,两个过程并不会按照顺序执行,也就是说,gulp并不会等你压缩完 js 再压缩 css.因为上面两个过程是 并发执行 的.

在上面的代码里面,两个流程是同时开始的,什么时候结束的我们并不关心.因为两个流程毫不相关呀~不会因为第一个流程影响到第二个流程,这是没问题的.

多个独立的任务?

很多时候,我们都会把互不相关的流程独立成一个任务,上面的代码改完后,就像这样:

gulp.task('minifyjs', function() {
    gulp.src('src/js/*.js')
        .pipe(uglify()) //压缩js
        .pipe(gulp.dest('dist/js'));
});

gulp.task('minifycss', function() {
    gulp.src('src/css/*.css')
        .pipe(cleanCSS()) //压缩css
        .pipe(gulp.dest('dist/css'));
});

gulp.task('minify',['minifyjs','minifycss']);

到时只需要在命令行输入 gulp minify 就会自动压缩 js 和 css.但是和刚才一样,这两个任务也是 并发执行 的.它不会根据你在括号里的书写顺序而顺序执行.

首先来看看 官方API 中是怎么写的.

task的语法是这样的:

gulp.task(name [, deps] [, fn]);

如果你定义了 deps, 那么任务将会先 并发执行 deps 中的所有任务,再执行这个任务本身.也就是说,我们可以利用这个参数来执行一些 有相关联的任务.

比如说,在 压缩js 之前,我们要先清空js目录:

gulp.task('clean:js', function () {
    del(['dist/js']);
});

gulp.task('minifyjs',["clean:js"], function() {
    gulp.src('src/js/*.js')
        .pipe(uglify()) //压缩js
        .pipe(gulp.dest('dist/js'));
});

在命令行中执行 gulp minifyjs 之后,结果会像这样子:
clean.png

也就是他确实会按照依赖顺序先执行 clean:js 任务,但是!他并没有执行我们的 minifyjs 任务.这是为什么呢?

官方API中是这么说的:

Note: Are your tasks running before the dependencies are complete? Make sure your dependency tasks are correctly using the async run hints: take in a callback or return a promise or event stream.
译: 你的任务是不是在依赖任务完成之前就运行了呢?要确保你的依赖任务使用了正确的异步方法:执行一个回调函数,或者返回一个promise或者返回一个事件流.

这里用上面说的方法来 修缮 上面的程序

一.执行回调函数

gulp.task('clean:js', function (cb) {
    del(['dist/js']);
    cb(); //执行回调函数
});

gulp.task('minifyjs',["clean:js"], function() {
    gulp.src('src/js/*.js')
        .pipe(uglify()) //压缩js
        .pipe(gulp.dest('dist/js'));
});

二.返回一个事件流

假设我们要让 压缩js 和 压缩css 顺序执行,可以这么做:

gulp.task('minifyjs', function() {
    var stream = gulp.src('src/js/*.js')
        .pipe(uglify()) //压缩js
        .pipe(gulp.dest('dist/js'));
    return stream;
});

gulp.task('minifycss',['minifyjs'], function() {
    gulp.src('src/css/*.css')
        .pipe(cleanCSS()) //压缩css
        .pipe(gulp.dest('dist/css'));
});

三.使用 .on() 监听 end 事件

这是执行回调函数的一个变种,他可以让你在 pipe 中的事情完成后处理一点其他事情再执行回调函数.

gulp.task('minifyjs', function(cb) {
    gulp.src('src/js/*.js')
        .pipe(uglify()) //压缩js
        .pipe(gulp.dest('dist/js'))
        .on(end,function(){
                   //可以在这里处理其他事情
                   cb();
                });
});

gulp.task('minifycss',['minifyjs'], function() {
    gulp.src('src/css/*.css')
        .pipe(cleanCSS()) //压缩css
        .pipe(gulp.dest('dist/css'));
});

流事件常用的有4种:

  • data - 当有数据可读时触发。

  • end - 没有更多的数据可读时触发。

  • error - 在接收和写入过程中发生错误时触发。

  • finish - 所有数据已被写入到底层系统时触发。


默认情况下,任务与任务之间会最大程度地并发运行,他们不会等待其他任务完成后再运行什么的.除非:

  1. 告诉你的任务整个流程什么时候完成(执行回调/返回事件流/返回promise)

  2. 告诉一个任务依赖于哪一个任务,并且这个依赖任务满足第一点要求.

  gulp