Search code examples
javascriptangularjsgulpbrowserifycommonjs

Can browserify require a vinyl file generated in gulp?


I've just started using gulp and browserify and I need some help with this problem:

I'm using a lib called ng-autobootstrap to generate a browserify compatible file, which is later on required in the main script. Here's my autobootstrap task:

gulp.task "autobootstrap", ->
  gulp.src("source/**/*.{coffee,js}",
    read: false
    base: "source"
  )
  .pipe(ngAutoBootstrap(
    moduleTypes:
      animation:
        path: "**/animations/*.{coffee,js}",
      constant:
        path: "**/constants/*.{coffee,js}",
      controller:
        path: "**/controllers/*.{coffee,js}",
      directive:
        path: "**/directives/*.{coffee,js}",
      factory:
        path: "**/factories/*.{coffee,js}",
      filter:
        path: "**/filters/*.{coffee,js}",
      provider:
        path: "**/providers/*.{coffee,js}",
      service:
        path: "**/services/*.{coffee,js}",
      value:
        path: "**/values/*.{coffee,js}",
      # config modules are pulled in like this:
      # app.config(require("./path/to-config"))
      config:
        path: "**/*-config.{coffee,js}"
  ))

If I add .pipe(gulp.dest("./source/")), it will create a bootstrap.js file in the source directory, but this is not exactly what I want, I would rather keep that directory clean. As far as I understand, up to now I have a vinyl file in memory, with the following content:

'use strict';

module.exports = function(app) {
    // Controllers
    app.controller('AppController', require('./controllers/app-controller'));
    app.controller('UsersController', require('./controllers/users-controller'));
    // ... and so on
};

Let's suppose the source/js/main.js file looks like this:

app = angular.module("app");
require("./bootstrap")(app); // this is the file generated by ng-autobootstrap

And a simple browserify task which creates the build/bundle.js file:

browserify = require('browserify')
gulp = require('gulp')
source = require('vinyl-source-stream')

gulp.task 'browserify', ->
  browserify('./source/main.js')
    .bundle()
    .pipe(source('bundle.js'))
    .pipe(gulp.dest('./build/'))

Now, if I modify the autobootstrap to write the file to disc first, then run browserify, this is all fine, the ./bootstrap file will be there. But is there a way to avoid writing to disc? Something like adding a vinyl file to browserify's search tree?


Solution

  • Use b.require to make a file available from outside of the bundle. And in order to use the vinyl streams, that Gulp uses/emits, with Browserify; we make a small inline transform using through2.obj to emit only the contents.

    A note on using b.require is that you need to b.exclude so that module-deps doesn't try to resolve it in the node_modules directories, etc. See issues #908 and #1106 for more information.

    var gulp = require('gulp');
    var through = require('through2');
    var source = require('vinyl-source-stream');
    var browserify = require('browserify');
    
    gulp.task('browserify-bundle', function() {
        return browserify('./test/main.js')
            // We need to exclude the required module so `module-deps` doesn't try to resolve it in the `node_modules` directories, etc
            // Suggested here: https://github.com/substack/node-browserify/issues/908#issuecomment-74909062
            //      See also: https://github.com/substack/node-browserify/issues/1106
            .exclude('some-func')
            // Then add in the module to the bundle
            .require(
                gulp.src('./test/hidden-some-func.js')
                    // Any plugins here....
                    // .pipe(ngAutoBootstrap(..)
                    //
                    // Then convert it to a object stream with only the `contents` for browserify to consume
                    .pipe(through.obj(function(chunk, env, cb) {
                        if (chunk.isStream()) {
                            self.emit('error', new gutil.PluginError(PLUGIN_NAME, 'Cannot operate on stream'));
                        }
                        else if (chunk.isBuffer()) {
                            this.push(chunk.contents);
                        }
    
                        // "call callback when the transform operation is complete."
                        cb();
                    })),
                {
                    // Dependency name to inject
                    expose: 'some-func',
                    // So that relative requires will be resolvable
                    basedir: './test/'
                }
            )
            .bundle()
            .pipe(source('bundle.js'))
            .pipe(gulp.dest('dest'));
    });