hughsk / vinyl-transform

Use standard text transform streams to write fewer gulp plugins
MIT License
55 stars 7 forks source link

Error: write after end when used with watchify #1

Closed pmdarrow closed 9 years ago

pmdarrow commented 10 years ago

I'm using vinly-transform with watchify in the following gulp task:

'use strict';

var browserify = require('browserify');
var browserifyShim = require('browserify-shim');
var gulp = require('gulp');
var watchify = require('watchify');
var transform = require('vinyl-transform');

module.exports = gulp.task('watchify', function () {
  var bundler = transform(function(filename) {
    return watchify(browserify(filename, {
      debug: true,
      cache: {}, packageCache: {}, fullPaths: true // Required watchify args
    }))
      .transform(browserifyShim)
      .on('update', bundle)
      .bundle();
  });

  function bundle() {
    return gulp.src(config.paths.src.entryPoint)
      .pipe(bundler)
      .pipe(gulp.dest(config.paths.dest.build.scripts))
  }

  return bundle();
});

When the task first runs, it starts fine. But as soon as I change a file, I get the following error:

[16:47:08] Starting 'watchify'...
[16:47:11] Finished 'watchify' after 2.68 s

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: write after end
    at writeAfterEnd (/Users/pmdarrow/code/client/node_modules/vinyl-transform/node_modules/through2/node_modules/readable-stream/lib/_stream_writable.js:144:12)
    at Transform.Writable.write (/Users/pmdarrow/code/client/node_modules/vinyl-transform/node_modules/through2/node_modules/readable-stream/lib/_stream_writable.js:192:5)
    at write (/Users/pmdarrow/code/client/node_modules/gulp/node_modules/vinyl-fs/node_modules/through2/node_modules/readable-stream/lib/_stream_readable.js:623:24)
    at flow (/Users/pmdarrow/code/client/node_modules/gulp/node_modules/vinyl-fs/node_modules/through2/node_modules/readable-stream/lib/_stream_readable.js:632:7)
    at DestroyableTransform.pipeOnReadable (/Users/pmdarrow/code/client/node_modules/gulp/node_modules/vinyl-fs/node_modules/through2/node_modules/readable-stream/lib/_stream_readable.js:664:5)
    at DestroyableTransform.EventEmitter.emit (events.js:92:17)
    at emitReadable_ (/Users/pmdarrow/code/client/node_modules/gulp/node_modules/vinyl-fs/node_modules/through2/node_modules/readable-stream/lib/_stream_readable.js:448:10)
    at emitReadable (/Users/pmdarrow/code/client/node_modules/gulp/node_modules/vinyl-fs/node_modules/through2/node_modules/readable-stream/lib/_stream_readable.js:444:5)
    at readableAddChunk (/Users/pmdarrow/code/client/node_modules/gulp/node_modules/vinyl-fs/node_modules/through2/node_modules/readable-stream/lib/_stream_readable.js:187:9)
    at DestroyableTransform.Readable.push (/Users/pmdarrow/code/client/node_modules/gulp/node_modules/vinyl-fs/node_modules/through2/node_modules/readable-stream/lib/_stream_readable.js:149:10)

Do you know if I'm using vinyl-transform properly in this case? It looks like https://github.com/wearefractal/vinyl-fs/issues/25 might be related, but I'm not sure.

mlmorg commented 9 years ago

Did you ever find out why this was happening or how to fix it?

hughsk commented 9 years ago

The problem here is that you're reusing the vinyl-transform stream.

Once gulp.src has finished outputting files, it'll attempt to close the streams you're piping it to – in this case, the vinyl-transform stream. So the second time it runs, the stream will already be closed, causing that error.

You could get the result you're after like so:

module.exports = gulp.task('watchify', function () {
  var bundler = watchify(browserify(filename, {
    debug: true,
    cache: {}, packageCache: {}, fullPaths: true // Required watchify args
  })).transform(browserifyShim)
     .on('update', bundle);

  function bundle() {
    var bundle = transform(function(filename) {
      return bundler.bundle();
    });

    return gulp.src(config.paths.src.entryPoint)
      .pipe(bundle)
      .pipe(gulp.dest(config.paths.dest.build.scripts))
  }

  return bundle();
});

In this case, you're creating a fresh vinyl-transform stream every time you bundle, and bundler.bundle() creates a new stream for you too :)

chaddjohnson commented 9 years ago

@hughsk Thank you for your suggestion, but unfortunately it does not work. filename is not defined:

ReferenceError: filename is not defined
    at Gulp.gulp.task.gulp.src.pipe.jshint.curly (/Users/chad/development/web/endpipe/app_site/gulpfile.js:52:39)
    at module.exports (/Users/chad/development/web/endpipe/app_site/node_modules/gulp/node_modules/orchestrator/lib/runTask.js:34:7)
    at Gulp.Orchestrator._runTask (/Users/chad/development/web/endpipe/app_site/node_modules/gulp/node_modules/orchestrator/index.js:273:3)
    at Gulp.Orchestrator._runStep (/Users/chad/development/web/endpipe/app_site/node_modules/gulp/node_modules/orchestrator/index.js:214:10)
    at Gulp.Orchestrator.start (/Users/chad/development/web/endpipe/app_site/node_modules/gulp/node_modules/orchestrator/index.js:134:8)
    at runNextSet (/Users/chad/development/web/endpipe/app_site/node_modules/run-sequence/index.js:74:16)
    at Gulp.onTaskEnd (/Users/chad/development/web/endpipe/app_site/node_modules/run-sequence/index.js:63:5)
    at Gulp.EventEmitter.emit (events.js:117:20)
    at Gulp.Orchestrator._emitTaskDone (/Users/chad/development/web/endpipe/app_site/node_modules/gulp/node_modules/orchestrator/index.js:264:8)
    at /Users/chad/development/web/endpipe/app_site/node_modules/gulp/node_modules/orchestrator/index.js:275:23

From my gulpfile:

var bundler = watchify(browserify(filename, {cache: {}, packageCache: {}, fullPaths: true}))
    .transform(hbsfy)
    .transform(nodeLessify)
    .on('update', bundle)

function bundle() {
    var bundle = transform(function(filename) {
        return bundler.bundle();
    });

    return gulp.src('src/app.js')
        .pipe(bundle)
        .pipe(gulpif(environment === 'production', uglify()))
        .on('error', handleError)
        .pipe(gulp.dest('build'));
}

return bundle();
hughsk commented 9 years ago

@chaddjohnson you need to define filename, it's a variable which should point to your browserify entry file:

var path = require('path')

var filename = path.join(__dirname, 'src/index.js')
chaddjohnson commented 9 years ago

Nice!! This works! Thank you! Finally I can use Browserify 8.

hughsk commented 9 years ago

Glad you got it working :)