deepak1556 / gulp-browserify

Bundle modules with BrowserifyJS
MIT License
195 stars 45 forks source link

Unable to Run Back-to-Back gulp-browserify Tasks #75

Open quidmonkey opened 10 years ago

quidmonkey commented 10 years ago

I've inherited a large legacy codebase, and I have decided to implement gulp + browserify for our build step. Unfortunately, due to the way the app was architected, it doesn't make sense to compile everything down to a single app.js file. Instead, I have broken out the compiled files for each of the feature modules.

During my build step, I want to run a gulp task that looks like this:

gulp.task('browserify:build, ['browserify:feature1', 'browserify:feature2', 'browserify:feature3']);

Where each sub-task calls gulp-browserify to compile the javascript to the associated feature module. I should note that all three feature modules as pull in a shared core module.

Unfortunately, after calling the 'browserify:build' task and attempting to run the app, I find that it errors out. For now, I have created a workaround that does this:

gulp.task('browserify:dev', function () { var exec = require('child_process').exec; var cmd = 'gulp browserify:feature1; gulp browserify:feature2; gulp browserify:feature3'; exec(cmd); });

This works, although is not ideal.

Thanks.

sogko commented 10 years ago

Hi @quidmonkey,

Firstly, I'd advised you replace to gulp-browserify and use the vanilla browserify library since

Refer to this sample gulpfile.js to see how it can be done

Secondly, could you post gist of the gulp.tasks involved? (browserify:feature1, browserify:feature2 etc).

I'm guessing that the gulp.tasks that you wrote could be unintentionally asynchronous, see gulpjs API documentation on async tasks

adam-lynch commented 10 years ago

@sogko wouldn't you need vinyl-buffer in your gulpfile too (after the source usage)?

sogko commented 10 years ago

@adam-lynch Yes, you are right. You may need to convert the vinyl source stream into a buffer if you want to pipe additional tasks (uglifying for example) which works on buffers for e.g.:

var gulp = require('gulp');
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var uglify = require('gulp-uglify');

gulp.task('browserify', function () {
  var b = browserify('./src/main.js', {});
  var stream = bundle
    .pipe(source('bundle.js'))
    .pipe(buffer())
    .pipe(uglify())
    .pipe(gulp.dest('./dist'));
  return stream;
});

I guess I was trying to give the barest of examples (write the bundle straight to a file without transformation). gulp.dest() is still able to consume a vinyl stream and write to a file (its simply an alias to vinyl-fs.dest())

Perhaps it would be a better idea to be more complete in the example to avoid confusion?

Thanks for pointing that out!

adam-lynch commented 10 years ago

@sogko Yeah I think so. It'll save some hassle / frustration. I ran into this myself when I was doing the conversion.

While we're here, if we have x entry files (i.e. x bundles), and we want to run the same transformations on each, then we've have to have x separate pipelines right? I.e. three calls to browserify. (Ignoring stream-combiner, etc.)

sogko commented 10 years ago

@adam-lynch Great question, you can try the following recipe that uses vinyl-transform for that:

var gulp = require('gulp');
var browserify = require('browserify');
var transform = require('vinyl-transform');
var uglify = require('gulp-uglify');

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

   // use `vinyl-transform` to wrap around the regular ReadableStream returned by b.bundle();
   // so that we can use it down a vinyl pipeline as a vinyl file object
  var browserified = transform(function(filename) {
    var b = browserify(filename);
    return b.bundle();
  });

  return gulp.src(['./src/*.js'])
    .pipe(browserified)
    .pipe(uglify())
    .pipe(gulp.dest('./dist'));
});

Note that vinyl-transform takes care of both streaming and buffered vinyl file objects, so we don't have to explicitly use vinyl-buffer in this example.

Personally, I think it gets easier to write gulp recipes once we realise that gulp 'streaming' pipelines does not actually use regular NodeJS Stream but actually use vinyl file objects that wraps around Streams. And all that it takes is to transform one to the other, and we won't be limited to just using gulp-* wrappers for our build needs.

adam-lynch commented 10 years ago

@sogko oooh that's lovely. Shouldn't that be a recipe too?

Is it much slower than the previous example? Because if not, then you could just always advocate this. It's clearer, there are less dependencies and it fits in more with gulp since you just use gulp.src.

On the last paragraph; yeah, that makes sense. Gulp has pretty much been the gateway drug to Node for me. So, I've mostly only gone as far as using event-stream.map, etc in a custom pipe. I've been putting off reading the stream-handbook for way too long.

sogko commented 10 years ago

@adam-lynch yeah I think I agree with you that using vinyl-transform would be a better recipe to use than vinyl-source-stream + vinyl-buffer which can easily cause confusion and/or frustrations (had a lot of those before when starting out)

As far as performance, its not doing anything drastically different from the two libraries. I did a quick test of writing the same tasks using the two approach, doesn't seem to differ in terms of build time. Might need a heavier browserify use-case to be sure, maybe.

That handbook is a great resource! (I admit I have yet to read it end-to-end hah).

Wish gulpjs would come out with better documentation on their vinyl implementation soon and clear some things up.

adam-lynch commented 10 years ago

@sogko I think I'll need to update my browserify set up now to use vinyl-transform now instead of three pipelines with vinyl-source-stream & vinyl-buffer :smile: