Search code examples
node.jsgulpevent-stream

es.merge usage in gulp: Object #<Stream> has no method 'end'


I am struggling to get two parallel processing routes to work in gulp. My code looks like this:

gulp.task('build', function(){

    return gulp.src(src,{cwd:srcDir})
        .pipe(concat('sdk.js', {newLine:'\n\n'}))
        .pipe(gulp.dest('dist/'))
        .pipe(jshint())
        .pipe(jshint.reporter('default'))
        .pipe(es.merge(
            gulp.src('dist/sdk.js')
                .pipe(preprocess({context:{debug:true}}))
                .pipe(rename('sdk.debug.js')),
            gulp.src('dist/sdk.js')
                .pipe(preprocess({context:{}}))
                .pipe(uglify())
                .pipe(rename('sdk.min.js'))
        ))
        //some more processing
        .pipe(gulp.dest('dist/'))
        ;
});

I have found a suggestion here that such a way of forking and then merging streams should work. However, I get the error:

stream.js:79
    dest.end();
         ^
TypeError: Object #<Stream> has no method 'end'
    at Stream.onend (stream.js:79:10)
    at Stream.EventEmitter.emit (events.js:117:20)
    at end (C:\Users\user\Documents\proj\node-sdk\node_modules\gulp-
jshint\node_modules\map-stream\index.js:116:39)
    at Stream.stream.end (C:\Users\user\Documents\proj\node-sdk\node
_modules\gulp-jshint\node_modules\map-stream\index.js:122:5)
    at Stream.onend (stream.js:79:10)
    at Stream.EventEmitter.emit (events.js:117:20)
    at end (C:\Users\user\Documents\proj\node-sdk\node_modules\gulp-
jshint\node_modules\map-stream\index.js:116:39)
    at queueData (C:\Users\user\Documents\proj\node-sdk\node_modules
\gulp-jshint\node_modules\map-stream\index.js:62:17)
    at next (C:\Users\user\Documents\proj\node-sdk\node_modules\gulp
-jshint\node_modules\map-stream\index.js:71:7)
    at C:\Users\user\Documents\proj\node-sdk\node_modules\gulp-jshin
t\node_modules\map-stream\index.js:85:7

It seems that the problem lies with the usage of es.merge, as without it (one processing path) everything works as expected. Unfortunately, I don't have an extensive knowledge of node.js streams, so I cannot identify the cause of this problem. My version of Node is 0.10.28, gulp 3.6.2 and event-stream is 3.1.5


Solution

  • es.merge cannot be used as the target of a pipe because it is not a proper WriteStream. It implements write() but not end() so it will work to forward along the incoming stream data, but when the upstream source is finished, es.merge does not handle the end event. I don't know if this is the intended behavior for es.merge, but at least in its current implementation, it can only be used as a source.

    https://github.com/dominictarr/event-stream/blob/master/index.js#L32

    An alternate solution would be to split your task into two separate tasks and use gulp dependencies:

    gulp.task('build-concat', function() {
        return gulp.src(src,{cwd:srcDir})
            .pipe(concat('sdk.js', {newLine:'\n\n'}))
            .pipe(gulp.dest('dist/'))
            .pipe(jshint())
            .pipe(jshint.reporter('default'));
    });
    
    gulp.task('build', ['build-concat'], function() {
        return es.merge(
            gulp.src('dist/sdk.js')
                .pipe(preprocess({context:{debug:true}}))
                .pipe(rename('sdk.debug.js')),
            gulp.src('dist/sdk.js')
                .pipe(preprocess({context:{}}))
                .pipe(uglify())
                .pipe(rename('sdk.min.js'))
        ))
        //some more processing
        .pipe(gulp.dest('dist/'))
        ;
    });