New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

exception: browserify + vinyl-transform #1198

Closed
BibbyChung opened this Issue Apr 6, 2015 · 12 comments

Comments

Projects
None yet
8 participants
@BibbyChung

BibbyChung commented Apr 6, 2015

Hi,

It's my gulpfile.js setting.

//gulpfile.js

var gulp = require("gulp");
var browserify = require("browserify");
var transform = require("vinyl-transform");
var rename = require("gulp-rename");

gulp.task("scripts", function () {
    var browserified = transform(function (filename) {
        var b = browserify(filename);

        return b.bundle();
    });

    return gulp.src([
        "./test/myApp/_module.js"
    ])
    .pipe(browserified)
    .pipe(rename("app.js"))
    .pipe(gulp.dest("./test/"));
});

When I use latest version of browserify, this exception are as follows.

_stream_readable.js:540
    var ret = dest.write(chunk);
                   ^
TypeError: undefined is not a function
    at Producer.ondata (_stream_readable.js:540:20)
    at Producer.emit (events.js:107:17)
    at Producer.Readable.read (_stream_readable.js:373:10)
    at flow (_stream_readable.js:750:26)
    at resume_ (_stream_readable.js:730:3)
    at _stream_readable.js:717:7
    at process._tickCallback (node.js:355:11)
Process terminated with code 1.

However, I downgrade to v9.0.4, anything will be ok.
Who can talk me how to fix it ?

thanks

@iamcdonald

This comment has been minimized.

Show comment
Hide comment
@iamcdonald

iamcdonald Apr 6, 2015

HI Bibby,

there seem to be a couple of other issues raised around this topic.

Paraphrasing here but, browserify's bundle() is documented as returning readable stream whereas vinyl-transform expects a transform/duplex stream which is readable and writeable. This worked in the past as .bundle() was at times returning a duplex stream however this is now fixed in line with the docs.

I'm currently using 'through2' and something akin to the following

gulp.src('./src/index.js')
    .pipe(through2.obj(function (file, enc, next){
            browserify(file.path)
                .transform('stripify')
                .bundle(function(err, res){
                    // assumes file.contents is a Buffer
                    file.contents = res;
                    next(null, file);
                });
        }))
    .pipe(gulp.dest('./build/'))

which was taken from aymanrady on this thread which has a few other recipes for using browserify within gulp.

Hope that helps.

iamcdonald commented Apr 6, 2015

HI Bibby,

there seem to be a couple of other issues raised around this topic.

Paraphrasing here but, browserify's bundle() is documented as returning readable stream whereas vinyl-transform expects a transform/duplex stream which is readable and writeable. This worked in the past as .bundle() was at times returning a duplex stream however this is now fixed in line with the docs.

I'm currently using 'through2' and something akin to the following

gulp.src('./src/index.js')
    .pipe(through2.obj(function (file, enc, next){
            browserify(file.path)
                .transform('stripify')
                .bundle(function(err, res){
                    // assumes file.contents is a Buffer
                    file.contents = res;
                    next(null, file);
                });
        }))
    .pipe(gulp.dest('./build/'))

which was taken from aymanrady on this thread which has a few other recipes for using browserify within gulp.

Hope that helps.

@BibbyChung

This comment has been minimized.

Show comment
Hide comment
@BibbyChung

BibbyChung Apr 6, 2015

It works fine. ^^
Thanks

BibbyChung commented Apr 6, 2015

It works fine. ^^
Thanks

@BibbyChung BibbyChung closed this Apr 6, 2015

BibbyChung added a commit to BibbyChung/ToDoListWithTypeScript that referenced this issue Apr 6, 2015

@Tanoemon

This comment has been minimized.

Show comment
Hide comment
@Tanoemon

Tanoemon Jul 15, 2015

@iamcdonald

How would you write when you want to do something like replacement strings before browserify like the below code?

gulp.src('./src/index.js')
    .pipe(replace('{{Server}}', 'http://localhost:3000')) // doesn't work..
    .pipe(through2.obj(function (file, enc, next){
            browserify(file.path)
                .transform('stripify')
                .bundle(function(err, res){
                    // assumes file.contents is a Buffer
                    file.contents = res;
                    next(null, file);
                });
        }))
    .pipe(gulp.dest('./build/'))

Tanoemon commented Jul 15, 2015

@iamcdonald

How would you write when you want to do something like replacement strings before browserify like the below code?

gulp.src('./src/index.js')
    .pipe(replace('{{Server}}', 'http://localhost:3000')) // doesn't work..
    .pipe(through2.obj(function (file, enc, next){
            browserify(file.path)
                .transform('stripify')
                .bundle(function(err, res){
                    // assumes file.contents is a Buffer
                    file.contents = res;
                    next(null, file);
                });
        }))
    .pipe(gulp.dest('./build/'))
@iamcdonald

This comment has been minimized.

Show comment
Hide comment
@iamcdonald

iamcdonald Jul 15, 2015

@nanila
Because you have to pass a browserify a file path rather than the file content, in the above example browserify will re-read the file you've pointed to which obviously won't contain the changes you've made via 'rename' as those changes haven't been written back out to the file in question.

You could use a gulp.dest stage to write out your 'rename' changes before passing through browserify e.g.

gulp.src('./src/index.js')
    .pipe(replace('{{Server}}', 'http://localhost:3000')) // doesn't work..
    .pipe(gulp.dest('sandbox/')) // index.js with 'rename'  changes now exists in src/sandbox/index.js
    .pipe(through2.obj(function (file, enc, next){
            browserify(file.path) // file.path here will now be src/sandbox/index.js
                .transform('stripify')
                .bundle(function(err, res){
                    // assumes file.contents is a Buffer
                    file.contents = res;
                    next(null, file);
                });
        }))
    .pipe(gulp.dest('./build/'))

Obviously at the end of the task you still have sandbox/index.js which you may want to clean up or add sandbox/ to your .gitignore etc.

iamcdonald commented Jul 15, 2015

@nanila
Because you have to pass a browserify a file path rather than the file content, in the above example browserify will re-read the file you've pointed to which obviously won't contain the changes you've made via 'rename' as those changes haven't been written back out to the file in question.

You could use a gulp.dest stage to write out your 'rename' changes before passing through browserify e.g.

gulp.src('./src/index.js')
    .pipe(replace('{{Server}}', 'http://localhost:3000')) // doesn't work..
    .pipe(gulp.dest('sandbox/')) // index.js with 'rename'  changes now exists in src/sandbox/index.js
    .pipe(through2.obj(function (file, enc, next){
            browserify(file.path) // file.path here will now be src/sandbox/index.js
                .transform('stripify')
                .bundle(function(err, res){
                    // assumes file.contents is a Buffer
                    file.contents = res;
                    next(null, file);
                });
        }))
    .pipe(gulp.dest('./build/'))

Obviously at the end of the task you still have sandbox/index.js which you may want to clean up or add sandbox/ to your .gitignore etc.

@Tanoemon

This comment has been minimized.

Show comment
Hide comment
@Tanoemon

Tanoemon Jul 15, 2015

@iamcdonald

Oh, I got it. Thanks!! I will create its temporary file!

Tanoemon commented Jul 15, 2015

@iamcdonald

Oh, I got it. Thanks!! I will create its temporary file!

@limdauto

This comment has been minimized.

Show comment
Hide comment
@limdauto

limdauto Sep 27, 2015

@iamcdonald @nanila I don't think you need to create a temporary file at all. Just use browserify(file) instead of browserify(file.path)

limdauto commented Sep 27, 2015

@iamcdonald @nanila I don't think you need to create a temporary file at all. Just use browserify(file) instead of browserify(file.path)

@PavelPolyakov

This comment has been minimized.

Show comment
Hide comment
@PavelPolyakov

PavelPolyakov Oct 17, 2015

@limdauto @iamcdonald

browserify(file) concept doesn't work.

This

gulp.src('./public/app/main.js')
        .pipe(through2.obj(function (file, enc, next) {
            browserify(file)
                .transform('vueify')
                .bundle(function (err, res) {
                    // assumes file.contents is a Buffer
                    file.contents = res;
                    next(null, file);
                });
        }))
        .on('error', function (error) {
            // If you want details of the error in the console
            console.log(error.stack);

            this.emit('end');
        })
        .pipe(plugins.rename('app.js'))
        .pipe(gulp.dest('./public/app/built'))
        .pipe(plugins.callback(function () {
            plugins.livereload.reload();
        }));

results to this:

/***/node_modules/gulp/node_modules/vinyl-fs/node_modules/vinyl/index.js:143
      throw new Error('File.contents can only be a Buffer, a Stream, or null.'
            ^
Error: File.contents can only be a Buffer, a Stream, or null.

Working example, for me, looks like this:

gulp.src('./public/app/main.js')
        .pipe(plugins.babel())
        .pipe(plugins.rename('main.es5.js'))
        .pipe(gulp.dest('./public/app/built'))
        .pipe(through2.obj(function (file, enc, next) {
            browserify(file)
                .transform('vueify')
                .bundle(function (err, res) {
                    // assumes file.contents is a Buffer
                    file.contents = res;
                    next(null, file);
                });
        }))
        .on('error', function (error) {
            // If you want details of the error in the console
            console.log(error.stack);

            this.emit('end');
        })
        .pipe(plugins.rename('app.js'))
        .pipe(gulp.dest('./public/app/built'))
        .pipe(plugins.callback(function () {
            plugins.livereload.reload();
        }));

As for me, it looks much worse comparing to gulp-browserify usage.

return gulp.src('./public/app/main.js')
        .pipe(plugins.babel())
        .pipe(plugins.browserify({
            transform: 'vueify'
        }))
        .on('error', function (error) {
            // If you want details of the error in the console
            console.log(error.stack);

            this.emit('end');
        })
        //.pipe(plugins.uglify({mangle:false}))
        .pipe(plugins.rename('app.js'))
        .pipe(gulp.dest('./public/app/built'))
        .pipe(plugins.callback(function () {
            plugins.livereload.reload();
        }));

However, as it is not supported anymore, we have no choice :(

PavelPolyakov commented Oct 17, 2015

@limdauto @iamcdonald

browserify(file) concept doesn't work.

This

gulp.src('./public/app/main.js')
        .pipe(through2.obj(function (file, enc, next) {
            browserify(file)
                .transform('vueify')
                .bundle(function (err, res) {
                    // assumes file.contents is a Buffer
                    file.contents = res;
                    next(null, file);
                });
        }))
        .on('error', function (error) {
            // If you want details of the error in the console
            console.log(error.stack);

            this.emit('end');
        })
        .pipe(plugins.rename('app.js'))
        .pipe(gulp.dest('./public/app/built'))
        .pipe(plugins.callback(function () {
            plugins.livereload.reload();
        }));

results to this:

/***/node_modules/gulp/node_modules/vinyl-fs/node_modules/vinyl/index.js:143
      throw new Error('File.contents can only be a Buffer, a Stream, or null.'
            ^
Error: File.contents can only be a Buffer, a Stream, or null.

Working example, for me, looks like this:

gulp.src('./public/app/main.js')
        .pipe(plugins.babel())
        .pipe(plugins.rename('main.es5.js'))
        .pipe(gulp.dest('./public/app/built'))
        .pipe(through2.obj(function (file, enc, next) {
            browserify(file)
                .transform('vueify')
                .bundle(function (err, res) {
                    // assumes file.contents is a Buffer
                    file.contents = res;
                    next(null, file);
                });
        }))
        .on('error', function (error) {
            // If you want details of the error in the console
            console.log(error.stack);

            this.emit('end');
        })
        .pipe(plugins.rename('app.js'))
        .pipe(gulp.dest('./public/app/built'))
        .pipe(plugins.callback(function () {
            plugins.livereload.reload();
        }));

As for me, it looks much worse comparing to gulp-browserify usage.

return gulp.src('./public/app/main.js')
        .pipe(plugins.babel())
        .pipe(plugins.browserify({
            transform: 'vueify'
        }))
        .on('error', function (error) {
            // If you want details of the error in the console
            console.log(error.stack);

            this.emit('end');
        })
        //.pipe(plugins.uglify({mangle:false}))
        .pipe(plugins.rename('app.js'))
        .pipe(gulp.dest('./public/app/built'))
        .pipe(plugins.callback(function () {
            plugins.livereload.reload();
        }));

However, as it is not supported anymore, we have no choice :(

@iamcdonald

This comment has been minimized.

Show comment
Hide comment
@iamcdonald

iamcdonald Oct 17, 2015

Hi @PavelPolyakov,

I can't really see the difference between your task and the one proposed above with regards to using through2 and browserify(file) but maybe I'm missing something?
It looks like you were maybe having problems with trying to pass non-transpiled es6 code straight into the task and you resolved it by first passing it through babel?

The only issue I can see with your task is that, assuming your entire codebase is written in es6, your task only seems to transpile main.js. Given you're using browserify you could offload the transpilation process onto babelify as a browserify transform.

Finally, as @limdauto pointed out, you don't need to write the temporary file to disk as you can pass the file itself into the browserify task. You're already doing but it means you shouldn't need the following line in your current task before the browserify process.

  .pipe(gulp.dest('./public/app/built'))

iamcdonald commented Oct 17, 2015

Hi @PavelPolyakov,

I can't really see the difference between your task and the one proposed above with regards to using through2 and browserify(file) but maybe I'm missing something?
It looks like you were maybe having problems with trying to pass non-transpiled es6 code straight into the task and you resolved it by first passing it through babel?

The only issue I can see with your task is that, assuming your entire codebase is written in es6, your task only seems to transpile main.js. Given you're using browserify you could offload the transpilation process onto babelify as a browserify transform.

Finally, as @limdauto pointed out, you don't need to write the temporary file to disk as you can pass the file itself into the browserify task. You're already doing but it means you shouldn't need the following line in your current task before the browserify process.

  .pipe(gulp.dest('./public/app/built'))
@PavelPolyakov

This comment has been minimized.

Show comment
Hide comment
@PavelPolyakov

PavelPolyakov Oct 17, 2015

@iamcdonald

indeed, in my case, I need to transpill main.js file, before it is loaded by browserify (and transformed with vueify).

I have mentioned, that I was not able to pass the file itself, to the browserify task, for some reason.

And this approach:
image

Led to the error.

However, I just found, that the only thing I really need, is to have my main file, also ready for "vuefication". The everything works well.

Here is the complete example, for Vue people, which again looks pretty, as for me:

return browserify('./public/app/main.vue')
        .transform('vueify')
        .bundle()
        .on('error', function (error) {
            // If you want details of the error in the console
            console.log(error.stack);

            this.emit('end');
        })
        .pipe(source('app.js'))
        .pipe(gulp.dest('./public/app/built'))
        .pipe(plugins.callback(function () {
            plugins.livereload.reload();
        }));

Thanks for the help!

PavelPolyakov commented Oct 17, 2015

@iamcdonald

indeed, in my case, I need to transpill main.js file, before it is loaded by browserify (and transformed with vueify).

I have mentioned, that I was not able to pass the file itself, to the browserify task, for some reason.

And this approach:
image

Led to the error.

However, I just found, that the only thing I really need, is to have my main file, also ready for "vuefication". The everything works well.

Here is the complete example, for Vue people, which again looks pretty, as for me:

return browserify('./public/app/main.vue')
        .transform('vueify')
        .bundle()
        .on('error', function (error) {
            // If you want details of the error in the console
            console.log(error.stack);

            this.emit('end');
        })
        .pipe(source('app.js'))
        .pipe(gulp.dest('./public/app/built'))
        .pipe(plugins.callback(function () {
            plugins.livereload.reload();
        }));

Thanks for the help!

@philkunz

This comment has been minimized.

Show comment
Hide comment
@philkunz

philkunz Oct 27, 2015

If someone is looking for an easy approach:
check out our https://www.npmjs.com/package/gulp-browser package

It works with the latest browserify and bundles any "require" by default.

var gulp = require("gulp");
var gulpBrowser = require("gulp-browser");

gulp.task('gulpBrowserTest',function() {
    var stream = gulp.src('./test/*.js')
        .pipe(gulpBrowser.browserify())
        .pipe(gulp.dest("./test/browserifiedJS/"));
    return stream;
});

philkunz commented Oct 27, 2015

If someone is looking for an easy approach:
check out our https://www.npmjs.com/package/gulp-browser package

It works with the latest browserify and bundles any "require" by default.

var gulp = require("gulp");
var gulpBrowser = require("gulp-browser");

gulp.task('gulpBrowserTest',function() {
    var stream = gulp.src('./test/*.js')
        .pipe(gulpBrowser.browserify())
        .pipe(gulp.dest("./test/browserifiedJS/"));
    return stream;
});
@aosmialowski

This comment has been minimized.

Show comment
Hide comment
@aosmialowski

aosmialowski Dec 19, 2015

@PavelPolyakov I've got the same error message when one of my modules has been requiring a non-existent module. I've spent almost 4 hours on this with exactly the same task as posted above.

/***/node_modules/gulp/node_modules/vinyl-fs/node_modules/vinyl/index.js:143
      throw new Error('File.contents can only be a Buffer, a Stream, or null.'
            ^
Error: File.contents can only be a Buffer, a Stream, or null.

aosmialowski commented Dec 19, 2015

@PavelPolyakov I've got the same error message when one of my modules has been requiring a non-existent module. I've spent almost 4 hours on this with exactly the same task as posted above.

/***/node_modules/gulp/node_modules/vinyl-fs/node_modules/vinyl/index.js:143
      throw new Error('File.contents can only be a Buffer, a Stream, or null.'
            ^
Error: File.contents can only be a Buffer, a Stream, or null.
@rivaros

This comment has been minimized.

Show comment
Hide comment
@rivaros

rivaros Jan 26, 2016

@philkunz Gulp-browser is not a solution as it is just a wrapper, which does not pass any parameters to browserify (like {debug: true}). I looked into source code of gulp-browser.

rivaros commented Jan 26, 2016

@philkunz Gulp-browser is not a solution as it is just a wrapper, which does not pass any parameters to browserify (like {debug: true}). I looked into source code of gulp-browser.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment