Gulp任务顺序

5

我在使用几个gulp任务时遇到了一些麻烦。我尝试了所有方法并按照文档进行操作,但似乎仍然无法正常工作。希望有人能帮忙。

我想做的是先进行Sass压缩,然后将结果同步到本地vagrant文件夹(而不是远程服务器),最后重新加载浏览器同步。

我遇到的问题是,gulp要求所有任务都同时运行,而我需要它们依次运行。所有任务单独运行都可以,但我在让它们顺序运行时遇到了麻烦。我尝试了回调和依赖项,但显然我漏掉了某些东西。

我的设置比较复杂,所有任务都在单独的js文件中,但我已经尝试将其组合到这个单独的github要点中,以便其他人可以帮助。感谢任何援助。

https://gist.github.com/CodeStalker/9661725dcaf105d2ed6c

我唯一让这个工作的方法是将rsync管道传输到sass压缩的末尾,并使用gulp-if包装它,使用server: true变量,这样只有在它知道正在运行虚拟机时才会执行rsync。这不是理想的。

2个回答

3
这是Gulp中人们经常遇到的共同问题,特别是那些从Grunt转换而来的人。Gulp是异步的极致,它总是想尽可能同时完成尽可能多的任务。
让任务按顺序运行的第一步是让gulp知道何时您的任务结束,有几种不同的方法可以实现这一点。
1)返回一个流,gulp将等待流的“end”事件作为该任务完成的触发器。例如:
gulp.task( "stream-task", function(){
  return gulp.src( srcGlob )
    .pipe(sass())
    .pipe(compressCSS())
    .pipe(gulp.dest( destGlob ));
});

2) 返回一个Promise,gulp将等待Promise进入已解决状态,然后才会将任务标记为完成。例如:(不完美,只是为了说明问题)

gulp.task( "promise-task", function() {
  return new Promise(function(resolve, reject){
    fs.readFile( "filename", function( err, data ){
      if( err ){ return reject(err); }
      return resolve( data );
    });
  });
});

3) 如果函数没有返回任何内容,但函数签名需要一个参数,则调用任务回调函数。该参数将是一个回调函数,您可以调用它来表示任务已完成。例如:

gulp.task( "cb-task", function( done ){
  fs.readFile( "filename", function( err, data ){
    // do stuff, call done...
    done();
  });
});

通常情况下,您将返回类似示例1的流,这是典型的gulp任务的样子。选项2和3更适用于当您正在执行不是真正基于流的传统gulp任务时。
接下来要做的事情是为一个任务设置另一个任务的“依赖项”。Gulp文档将其显示为以下方式:
gulp.task( "some-task-with-deps", [ "array-of-dep", "task-names" ], function(){ /* task body */ });

现在我不知道当前的状态,但是这些依赖任务没有按照正确的顺序运行存在一些问题。这最初是由于 gulp 的一个依赖项(我相信是 orchestrator)出现了问题所致。在 NPM 领域中有一个好心人制作了一个很好的小包,在缺陷被修复期间使用它。我开始使用它来排序我的任务,从未回头过。

https://www.npmjs.com/package/run-sequence

文档很好,所以我在这里不会详细介绍。基本上,run-sequence允许您明确地排序gulp任务,只要记住,如果您没有为每个任务实现上述三个选项之一,则它将无法工作。
看看您的代码片段,在您的任务中添加几个缺失的返回语句可能就可以解决问题了,但是作为示例,这是我在工作项目中的“dev”任务的样子...
gulp.task( "dev", function( done ){
  runSequence(
    "build:dev",
    "build:tests",
    "server:dev",
    [
      "less:watch",
      "jscs:watch",
      "lint:watch",
      "traceur:watch"
    ],
    "jscs:dev",
    "lint:dev",
    "tdd",
    done // <-- thats the callback method to gulp let know when this task ends
  );
});

此外,供参考,我的“build:dev”任务也使用了run-sequence
gulp.task( "build:dev", function( done ){
  runSequence(
    "clean:dev",
    [
      "less:dev",
      "symlink:dev",
      "vendor:dev",
      "traceur:dev"
    ],
    done // <-- thats the callback method to let know when this task ends
  );
});

如果需要按顺序运行任务,则将任务名称作为其自身参数添加到runSequence中。如果它们不冲突,则作为数组发送以使任务同时运行并加速构建过程。
关于监视任务,有一件事需要注意!通常,监视任务会无限期地运行,因此尝试从中返回“无限”流可能会使gulp认为该任务永远不会结束。在这种情况下,我将使用回调方法,即使任务仍在运行,也会让gulp认为任务已完成,类似于...
gulp.task( "watch-stuff", function( done ){
  gulp.watch( watchGlob )
    .on( "change", function( event ){ /* process file */ });

  done();
});

关于观察任务和如何进行增量构建的更多信息,请查看我前几天写的一个答案,增量 gulp less 构建

感谢您的详细回复。在发布问题之前,我已经尝试过其中的一些方法,但是当我添加了缺失的“return”到流中时,流就出现了问题。我还尝试了运行序列,但没有成功,可能是因为我似乎无法让它意识到流何时结束。 - James Steel
我唯一让它工作的方法是将rsync管道传输到sass放大的末尾,并使用server:true变量将其包装在gulp-if中,以便仅在它知道正在运行虚拟机时才执行rsync。这并不理想。也许我会简化事情,仔细重建,看看是否可以弄清楚为什么添加return后流会中断。 - James Steel
看起来你正在使用rsync同步到本地虚拟机,对吗? Vagrant的synced_folder设置不适用于你有什么原因吗? - ashwell
是的 - 对我来说没问题,但可能不适用于其他人。这个gulp设置是我构建的框架的一部分。我想允许使用任何本地或远程开发设置,而不仅仅是vagrant。我是Midas的作者http://midas.jamessteel.co.uk/,如果我能让它工作,这个rsync功能就是我正在尝试整合的东西,但我在学习Gulp的过程中。Midas可以在github上找到,如果你有任何改进gulp设置的想法,请随意探索。 :) 我正在使用同步的vagrant文件夹,但希望将node_modules和所有内容都排除在外,所以我只复制CSS、JS和字体。 - James Steel
太棒了!我找到时间一定会好好探索一下。 - ashwell

0

给你,我相信现在应该可以工作了。如果不行,请告诉我,我可能打错了字。 您的要点已修复

我认为您正在遇到(我没有足够的声望来发布链接,谷歌问题#96),这在4.x中已经解决了,但目前还未发布:-)。话虽如此,请查看这个hack:我的有关Gulp v3.x bug的帖子


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接