I am trying to slowly introduce Browserify into my site, but I don\'t want to rewrite all the js and I don\'t want duplicate instances of jquery and other libraries bundled
This can be done with a 1-liner:
echo "module.exports=window.jQuery" > node_modules/jquery.js
Add 1 line to your build script for each external dependency. No need to pass any special options to Browserify.
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 of bundle.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 then bundle.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.
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)
.