Shimming a jQuery plugin appears to be only for geniuses who throw salt over the correct shoulder.
However I did this....
var backbone = require('backbone');
global.jQuery = global.$ = backbone.$ = require('jquery');
require('./libs/jquery-modal');
$("body").Modal();
and it just works. (n.b. jquery is being loaded via debowerify)
Why does this work? Would shimming it mean I don't need to do the assignments to jquery
and $
?
And how is browserify able to handle my plugin code not being in the correct commonjs format?
I assume you are talking about the browserify-shim
.
Shimming is used for making commonjs-incompatible files browserifiable.
To be commonjs-compatible, a file must export something. Here is a simple commonjs module:
// mystring.js
module.exports = "Hello Stackoverflow";
Now in some other file, you could require mystring.js
and use it like this:
var str = require('./mystring.js');
console.log(str); // > "Hello Stackoverflow"
In older versions of jQuery (pre 1.11 and 2.1) nothing was exported. Instead jQuery would attach itself to the window
object. That goes against the whole concept of modularity, making your code depend on objects and values to be present in the global scope.
Loading files in the right order could be tricky in more complex environments. Especially if some config files change some global variables, and your script should be executed when window.foo
is set to "bar" but before other script updates window.foo
value to "qux".
When we try to use jQuery before it is loaded, we get a ReferenceError
:
<!-- index.hmtl -->
<script>
var $body = $('body'); // ReferenceError: Can't find variable: $
</script>
<script src="jquery.js">
That is where browserify-shim
comes into play.
In essence browserify-shim
does something like this:
// jquery-shim.js
loadScript('jquery.js') // now, window.$ contains a reference to the jQuery object
module.exports = window.$; // exports that jQuery object
window.$ = null;
Now you can use jQuery anywhere in your code, without relying on it to be present in the global scope:
<!-- product-page.hmtl -->
<script> <!-- script is inlined for demo purposes only -->
var $ = require('./jquery-shim.js');
var $body = $('body'); // this works now
</script>
It is about modularizing your project and keeping your global scope clean.