Search code examples
javascriptbrowserify

How to create vendor bundles with latest Browserify (6.x.x)?


Well, we have been using Browserify 2.x for some time now. We are going through some refactoring so we want to try update to latest Browserify to diminish future leaps in versions.

Unfortunately something has changed in how external bundles are handled. In the old version we could simply tell Browserify which modules to keep out of the bundle and require them from another one - basically what is described here.

From the version 5.0.0 some big change in Browserify internals happened. Let's take for example this command. The debug module is NPM module.

browserify -r debug -o vendor.js

Running this command in Browserify@4, the output file would look like this:

require=(function... {
    "debug":[function(require,module,exports){
        module.exports=require('2Bvkwp');
    },{}],
    "2Bvkwp":[function(require,module,exports){
        // actual code from debug module
    },{}]
});

Now with the Browserify@5 it looks like this:

require=(function... {
    1:[function(require,module,exports){
        // actual code from debug module
    },{}]
});

To complete the equation, I have simple file that contains require('debug') and this is bundled with command browserify -x debug -e index.js -o main.js. Internal dependency is set to undefined for the debug module, which is alright.

If you would look at the prelude.js file, there is logic that simply uses previously defined global require (stored in previousRequire variable) to find modules that are not defined within current bundle. BUT since vendor.js doesn't expose anything like debug module, it cannot succeed.

All I have been able to find is this line in the changelog:

hashing is gone so expose: true or explicit expose id is required for doing multi-export bundles

I am unable to find what does that actually means :(


Solution

  • You should able to create your vendor bundle like this:

    browserify -r debug > vendor.js
    

    And then create your application bundle like this:

    browserify index.js -x debug > main.js
    

    This works just fine (I'm using [email protected]).

    Basically, even if require('debug'); won't work in the browser console, browserify can find the debug module in the vendor bundle as long as the bundles are loaded in the right order, i.e:

    <script src="vendor.js"></script>
    <script src="main.js"></script>
    

    It doesn't have to expose the dependency to external code, only to other browserify bundles.