【问题标题】:Gulp: how do I pipe through a task that never finishes?Gulp:我如何处理一个永远不会完成的任务?
【发布时间】:2014-08-08 03:02:08
【问题描述】:

我正在尝试为watchify 编写一个 gulp 插件,允许我将文件通过管道传输到其中。问题是我的任务从未真正“完成”,因为它坐在那里并监控一堆文件并根据需要重新构建。

那么我如何“通过”这个插件发送代码?

现在,我调用插件的任务被简化为:

gulp.src( '/path/to/js/*.js' )
    .pipe( watchifyPlugin() )
    .pipe( cfg.gulp.dest( '/path/to/build' ) )

我的watchifyPlugin 是:

module.exports = function( opts ){
    return through.obj( function( file, enc, cb ){
        // watchify file
        self.push( data ); // whenever any .js files are updated

        // never call cb()
    }
}

现在这适用于我的 glob 找到的第一个 .js 文件。但是,任何其他文件实际上都不会进入我的插件,我假设这是因为我从未调用过cb()。

那么我该怎么做呢?有没有办法在不调用cb() 的情况下继续写入流,这会关闭它,但仍然允许以前的管道继续?

换句话说:

  • index.js
    • watchify()
    • 到dest() 的管道很好,即使我一次又一次地打电话给self.push()
    • cb() 从未打过电话
  • index2.js
    • watchify() 在 cb() 调用 index.js 之前从未调用过,但这会“关闭”index.js 管道

【问题讨论】:

    标签: node.js stream gulp browserify watchify


    【解决方案1】:

    您以错误的方式使用 through,您必须在完成文件后调用回调(“数据”事件)。然而,关闭流的不是cb(),即使这样做也会发出end。

    您可以延迟结束事件并继续调用this.push 以发送新文件。

    类似

    var Through = require('through2').obj;
    var my_plugin = function() {
    
      var last_file = null; // as an example, last emitted file
    
      function handle_data = function(file, enc, done) { 
        this.push(file); // emit the file
        this.push(file); // just for kicks, emit it again
        last_file = file;
        done(); // done handling *this* file
      }
    
      function handle_end = function(done) {
         if(last_file) this.push(last_file); // emit the last file again
         done(); // handled the 'end' event
      }
    
      return Through(handle_data, handle_end);
    }
    

    这将在处理下一个文件之前发出每个文件两次,然后在处理完所有文件后(收到end 事件)再发出最后一个文件一次,然后发出end 事件。

    但是你为什么不使用gulp.watch 而只是在事情发生变化时再次运行任务呢?或者甚至使用 gulp-watch 插件在文件更改时发出文件?

    【讨论】:

    • 我知道我可以延迟事件,但关键是我需要延迟它永远。 watchify 在所有嵌套的所需 JS 文件上保持监视器打开,并在其中任何一个更改时重建父文件。在gulp.watch 中初始化它有两个缺点——它不监视包含的文件,并且每次都会进行完全重建而不是增量重建。
    • 哪个事件? end 还是 data?流始终是 data-data-data-data-end 或连续流:data-data-data ...因此,如果您想永远延迟数据事件(有效地使流连续),您需要 消耗并且不发出end 事件(所以不要在handle_end 中调用done())。您需要在数据事件中调用done()(无论您是否发出)。然后你可以从你的流中发出你想要的任何文件。但是,我仍然看不出这与gulp-watch 有什么不同,也许您可​​以扩展您的问题?最后,我同意@robrich 的回答。
    【解决方案2】:

    这是一个非常糟糕的主意。并非 gulp 中的所有内容都必须是插件,尤其是 browerify 和 watchify 插件一直被禁止。 (见https://github.com/gulpjs/plugins/blob/master/src/blackList.json。)如果你想运行watchify,直接使用watchify。来自https://github.com/gulpjs/gulp/blob/master/docs/recipes/fast-browserify-builds-with-watchify.md:

    var gulp = require('gulp');
    var source = require('vinyl-source-stream');
    var watchify = require('watchify');
    
    gulp.task('watch', function() {
      var bundler = watchify('./src/index.js');
    
      // Optionally, you can apply transforms
      // and other configuration options on the
      // bundler just as you would with browserify
      bundler.transform('brfs');
    
      bundler.on('update', rebundle);
    
      function rebundle () {
        return bundler.bundle()
          .pipe(source('bundle.js'))
          .pipe(gulp.dest('./dist'))
      }
    
      return rebundle();
    });
    

    【讨论】:

    • 不,这不是一个“非常糟糕的主意”。制作这个插件的全部意义在于摆脱在任务中定义特定输出文件的反模式。
    • browserify 流只会发出 one 文件并且它必须有一个名称,我不明白这是一个反模式。 (你总是可以要求一个 config.json 并在那里配置你的文件名)
    • 这就是重点——它只发出一个文件。这是一个非常非常狭窄的用例,即使它是一个常见的用例。我想要一个发出多个捆绑文件的管道。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-29
    相关资源
    最近更新 更多