10

I am learning browserify and I am trying to do two basic things with it:

  1. Transform (via shim) non-CommonJS modules for ease-of-use and dependency tracking
  2. Bundle the libraries that are project-specific

I've found a working process for how to do all of this and automate it with Gulp. This works and produces the right output but, I am curious if it could be made simpler. It seems like I have to duplicate a lot of configuration on the project-based bundles. Here is the working example:

package.json
invalid comments added for clarification

{
    //project info and dependencies omitted

    //https://github.com/substack/node-browserify#browser-field
    "browser": { //tell browserify about some of my libraries and where they reside
        "jquery": "./bower_components/jquery/dist/jquery.js",
        "bootstrap": "./bower_components/bootstrap/dist/js/bootstrap.js"
    },
    "browserify": {
        //https://github.com/substack/node-browserify#browserifytransform
        "transform": [
            "browserify-shim"
        ]
    },
    "browserify-shim": { 
       //shim the modules defined above as needed 
        "jquery": {
            "exports": "$"
        },
        "bootstrap": {
            "depends": "jquery:$"
        }
    }
}

config.js
contains all task-runner related configuration settings

module.exports = {

    browserify: {
        // Enable source maps and leave un-ulgified
        debug: true,
        extensions: [],
        //represents a separate bundle per item
        bundleConfigs: [
            {
                 //I really want to refer to the bundles here made in the package.json but 
                 //if I do, the shim is never applied and the dependencies aren't included
                 entries: ['/bundles/shared-bundle.js'], 
                 dest: '/dist/js',
                 outputName: 'shared.js'
            }
        ]
    },
    //...
};

shared-bundle.js
acts as a bundling file where node loads the dependencies and at this point, the shim has been applied

require('bootstrap');

browserify-task.js
contains the browserify bundling gulp task

//module requires omitted
gulp.task('browserify', function (callback) {
    var bundleQueue = config.bundleConfigs.length;
    var browserifyBundle = function (bundleConfig) {
        var bundler = browserify({
            entries: bundleConfig.entries,
            extensions: config.extensions,
            debug: config.debug,
        });

        var bundle = function () {
                return bundler.bundle()
                // Use vinyl-source-stream to make the stream gulp compatible
                .pipe(source(bundleConfig.outputName))
                // Specify the output destination
                .pipe(gulp.dest(bundleConfig.dest))
                .on('end', reportFinished);
        };

        var reportFinished = function () {
            if (bundleQueue) {
                bundleQueue--;
                if (bundleQueue === 0) {
                    // If queue is empty, tell gulp the task is complete
                    callback();
                }
            }
        };
        return bundle();
    };
    config.bundleConfigs.forEach(browserifyBundle);
});

In config.js where the first bundleConfig item's entries is a source to a file that has the require() modules, I'd like replace those with module names of modules defined in the package.json browser key.

In the config.js, if I change the bundle configuration to:

 bundleConfigs: [
      {
           entries: ['bootstrap'], 
           dest: '/dist/js',
           outputName: 'shared.js'
      }
 ]

and run the gulp task, it will include bootstrap.js but it doesn't run the shim transformation. jQuery is not being included at all.

This leaves me with a few questions:

  • Is there a better way to be bundling my js for use in a non-SPA application (ie am I going about this the wrong way)?
  • If not, is there a way to ensure the shim transformation is run prior to the bundling so that I can have my bundle configuration in one place?
Carrie Kendall
  • 11,124
  • 5
  • 61
  • 81
  • I'm confused as to what your overall goal is. You mention "non-SPA"; can you elaborate on that? What do your entries look like? You mentioned that certain libraries aren't showing up. In my experience, that means neither the entries nor a dependent of the entries refer to the library. – pgreen2 Dec 21 '14 at 03:04
  • @pgreen2 my goal is to bundle project dependencies in an environment that isn't a single page application ie.. more traditional I guess? The code posted above _works_. What doesn't work is when I use the `browser`entries in the browserify() entries option. It can see the main package (ie bootstrap in the example) but it doesn't see its shimmed dependency jquery. – Carrie Kendall Dec 21 '14 at 04:19
  • Can you throw a small project on github that demonstrates your problem that we can play with? – pgreen2 Dec 21 '14 at 05:22
  • @CarrieKendall did you ever figure this out? Having the same issue. – YPCrumble Sep 23 '15 at 17:09
  • @YPCrumble The code in the question works, it's just not efficient. I ended up using a config.js file to define my page-specific bundles, basically. – Carrie Kendall Sep 23 '15 at 17:11

1 Answers1

1

Certainly, you just have to tell your gulp file that it should shim first. Looks like you can add your own shim object when calling browserify from your gulp file. Check out this example

If you want to ensure everything is shimmed before you bundle them, use the deps array: "An array of tasks to be executed and completed before your task will run."

It would look something like this:

gulp.task('shim', function() {
  // ...
});

gulp.task('browserify', ['shim'], function(){
  // ...
});
  • [This](https://www.npmjs.com/package/gulp-browserify#browserify-shim) is an interesting example, I hadn't seen that before. Your code example is kind of useless though. I might see if I can apply my shims in the task, although this is less than ideal. I guess I am still left with the question: is there no way to tell browserify to run the globally registered shims in the stream instance? – Carrie Kendall Jan 05 '15 at 21:09
  • Feel free to go ahead and answer it. I'm actually not familiar with shimming. Glad the resource helped! – Keenan Lidral-Porter Jan 05 '15 at 21:45