How should project-level bundling be handled for non SPA use?

408 views Asked by At

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?
1

There are 1 answers

2
Keenan Lidral-Porter On

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(){
  // ...
});