How to make a jQuery plugin loadable with requirejs
There are some caveats with using shim configuration in RequireJS, pointed out on http://requirejs.org/docs/api.html#config-shim. Namely, "Do not mix CDN loading with shim config in a build" when you're using the optimizer.
I was looking for a way to use the same jQuery plugin code on sites both with and without RequireJS. I found this snippet for jQuery plugins at https://github.com/umdjs/umd/blob/master/jqueryPlugin.js. You wrap your plugin in this code, and it will work properly either way.
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module depending on jQuery.
define(['jquery'], factory);
} else {
// No AMD. Register plugin with global jQuery object.
factory(jQuery);
}
}(function ($) {
$.fn.yourjQueryPlugin = function () {
// Put your plugin code here
};
}));
Credit goes to jrburke; like so much javascript, it's functions inside functions acting on other functions. But I think I have unpacked what it's doing.
The function argument factory
in the first line is itself a function which is invoked to define the plugin on the $
argument. When no AMD-compatible loader is present, it's invoked directly to define the plugin on the global jQuery
object. That's just like the common plugin definition idiom:
function($)
{
$.fn.yourjQueryPlugin = function() {
// Plugin code here
};
}(jQuery);
If there is a module loader, then factory
is registered as the callback for the loader to invoke after loading jQuery. The loaded copy of jQuery is the argument. It's equivalent to
define(['jquery'], function($) {
$.fn.yourjQueryPlugin = function() {
// Plugin code here
};
})
You only need to do EITHER
define(["jquery"], // Require jquery
function($){
// Put here the plugin code.
// No need to return anything as we are augmenting the jQuery object
});
at the end of jquery-cookie.js, OR
requirejs.config( {
"shim": {
"jquery-cookie" : ["jquery"]
}
} );
anywhere before you include jquery-cookie (like wherever data-main points to, for instance).
The last code block you've posted is good for things like jQuery which get redistributed and may or may not be in an AMD environment. Ideally every jQuery plugin would have that set up already.
I prefer to keep included libraries as unadulterated as possible, so the global shim config once per page seems like the cleanest solution to me. That way upgrades are safer and CDNs become a possibility.
Just as an FYI to all some of the jquery plugins already use amd/require so you dont need to declare anything in the shim. In fact doing so might cause problems for you in some cases.
If you look in the jquery cookie JS you will see define calls and require(["jquery"]).
and in jquery.js you will see a call to define("jquery",[],function()...