Skip to content
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
Closed

exception: browserify + vinyl-transform #1198

BibbyChung opened this issue Apr 6, 2015 · 12 comments

Comments

@BibbyChung
Copy link

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
Copy link

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
Copy link
Author

It works fine. ^^
Thanks

@Tanoemon
Copy link

@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
Copy link

@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
Copy link

@iamcdonald

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

@limdauto
Copy link

@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
Copy link

@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
Copy link

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
Copy link

@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
Copy link

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
Copy link

@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
Copy link

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
Labels
None yet
Development

No branches or pull requests

8 participants