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 with my Browserify build.
If I build my module listing jquery as an external dependency, how do I then point it at my global jquery instance? Also the goal is to eliminate the mylibs global (example below), so I don't want to use it in my module.
This is what I'm trying to do (psudo-code). This would be in my site's repo - not the module's. The module would be installed with Bower:
var mylibs.jQuery = $.noConflict(); // global used by lots of existing code module.exports = { jquery: mylibs.jQuery // can be imported by my module as require('jquery') };
Something like that is what I'm trying to achieve. Is this possible?
Run the dist/ directory through Browserify to produce a package. bundle. js file and include that as a script tag. This seems to run without error, but the main function I need to instantiate the logic I need isn't present in the browser.
We can also include browserify itself as a dependency, however it isn't a dependency for the project to run – any user to our app can find Superman without needing to run Browserify. It is one of our devDependencies – modules required for developers to make updates to this app.
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)
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With