Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to output multiple bundles with browserify and gulp

I have browserify bundling up files and it's working great. But what if I need to generate multiple bundles?

I would like to end up with dist/appBundle.js and dist/publicBundle.js

gulp.task("js", function(){

    return browserify([
            "./js/app.js",
            "./js/public.js"
        ])
        .bundle()
        .pipe(source("bundle.js"))
        .pipe(gulp.dest("./dist"));

});

Obviously this isn't going to work since I am only specifying one output (bundle.js). I can accomplish this by repeating the above statement like so (but it doesn't feel right, because of the repetition):

gulp.task("js", function(){

    browserify([
            "./js/app.js"
        ])
        .bundle()
        .pipe(source("appBundle.js"))
        .pipe(gulp.dest("./dist"));


    browserify([
            "./js/public.js"
        ])
        .bundle()
        .pipe(source("publicBundle.js"))
        .pipe(gulp.dest("./dist"));

});

Is there a better way to tackle this? Thanks!

like image 583
Brian FitzGerald Avatar asked May 23 '14 18:05

Brian FitzGerald


3 Answers

I don't have a good environment to test this in right now, but my guess is that it would look something like:

gulp.task("js", function(){
    var destDir = "./dist";

    return browserify([
        "./js/app.js",
        "./js/public.js"
    ])
        .bundle()
        .pipe(source("appBundle.js"))
        .pipe(gulp.dest(destDir))
        .pipe(rename("publicBundle.js"))
        .pipe(gulp.dest(destDir));

});

EDIT: I just realized I mis-read the question, there should be two separate bundles coming from two separate .js files. In light of that, the best alternative I can think of looks like:

gulp.task("js", function(){
    var destDir = "./dist";

    var bundleThis = function(srcArray) {
        _.each(srcArray, function(source) {
            var bundle = browserify(["./js/" + source + ".js"]).bundle();
            bundle.pipe(source(source + "Bundle.js"))
                  .pipe(gulp.dest(destDir));
        });
    };

    bundleThis(["app", "public"]);
});
like image 75
urban_raccoons Avatar answered Nov 02 '22 02:11

urban_raccoons


Multiple bundles with shared dependencies

I recently added support for multiple bundles with shared dependencies to https://github.com/greypants/gulp-starter

Here's the array of browserify config objects I pass to my browserify task. At the end of that task, I iterate over each config, browserifying all the things.

config.bundleConfigs.forEach(browserifyThis);

browserifyThis takes a bundleConfig object, and runs browserify (with watchify if dev mode).

This is the bit that sorts out shared dependencies:

// Sort out shared dependencies.
// b.require exposes modules externally
if(bundleConfig.require) b.require(bundleConfig.require)
// b.external excludes modules from the bundle, and expects
// they'll be available externally
if(bundleConfig.external) b.external(bundleConfig.external)

This browserify task also properly reports when all bundles are finished (the above example isn't returning streams or firing the task's callback), and uses watchify when in devMode for super fast recompiles.

Brian FitzGerald's last comment is spot on. Remember that it's just JavaScript!

like image 24
Dan Tello Avatar answered Nov 02 '22 03:11

Dan Tello


gulp.task("js", function (done) {
  [
    "app",
    "public",
  ].forEach(function (entry, i, entries) {
    // Count remaining bundling operations to track
    // when to call done(). Could alternatively use
    // merge-stream and return its output.
    entries.remaining = entries.remaining || entries.length;

    browserify('./js/' + entry + '.js')
      .bundle()
      // If you need to use gulp plugins after bundling then you can
      // pipe to vinyl-source-stream then gulp.dest() here instead
      .pipe(
        require('fs').createWriteStream('./dist/' + entry + 'Bundle.js')
        .on('finish', function () {
          if (! --entries.remaining) done();
        })
      );
  });
});

This is similar to @urban_racoons answer, but with some improvements:

  • That answer will fail as soon as you want the task to be a dependency of another task in gulp 3, or part of a series in gulp 4. This answer uses a callback to signal task completion.
  • The JS can be simpler and doesn't require underscore.

This answer is based on the premise of having a known list of entry files for each bundle, as opposed to, say, needing to glob a list of entry files.

like image 31
JMM Avatar answered Nov 02 '22 03:11

JMM