How do I use Browserify with external dependencies?
Solution 1:
You can achieve that by using browserify-shim. Assuming that you've got a module named mymodule.js
that depends on jQuery in the global scope with the following contents:
var $ = require('jQuery');
console.log(typeof $);
-
Install browserify-shim:
npm install browserify-shim --save-dev
-
In package.json file, tell browserify to use browserify-shim as a transform:
{ "browserify": { "transform": [ "browserify-shim" ] } }
-
In package.json file, tell browserify-shim to map jQuery to the jQuery in the global scope:
{ "browserify-shim": { "jQuery": "global:jQuery" } }
-
Run browserify
browserify mymodule.js > bundle.js
If you examine bundle.js you will notice that require('jQuery')
is replaced with (window.jQuery)
.
Solution 2:
Browserify-shim is not transitive across node modules: it can be used to correctly shim top-level (in your own package.json) modules, but it cannot shim modules in other npm packages (with their own package.json files).
This is awkward when dealing with a node module that depends on the jQuery module (eg. a plugin that has a peer dependency), but the jQuery library should still be external.
My solution - similar in concept to the pseudo-code - was to create a custom 'preload shim', with the help of browserify itself.
-
Exclude the
jquery
module from the generation ofbundle.js
, but otherwise build the bundle normally.Install the appropriate node/npm modules to meet the build requirements. The to-be-excluded "external" modules will not be included in the bundle but are required to fulfill the compilation dependency resolution.
browserify -x jquery .. > dist/bundle.js
-
Create a file called jquery.js and include this content:
module.exports = window.jQuery; // or whatever
-
Generate a
shim.js
including just the previous file.browserify -r jquery.js > dist/shim.js
Then edit the file to use jQuery as the module name.
-
In the browser, load jquery (the external dependency),
shim.js
, and thenbundle.js
.When the bundle file tries to load the jquery module - which it does not define - it will fallback to the module (previously) defined in the shim file and run the custom code. In this case that's piping through a previously defined global.
Or: what browserify-shim "global:" tries to do, only actually .. globally.
Using the browserify module directly - instead of grunt, which I am re-growing to loathe - may have resulted in a 'more refined' solution.