How to make a jQuery plugin loadable with requirejs

Nicola Peluchetti picture Nicola Peluchetti · Jun 6, 2012 · Viewed 51.4k times · Source

I'm working with requirejs+jquery and i was wondering if there was a smart way to make a jQuery plugin work well with require.

For example i'm using jQuery-cookie. If i understood correctly i can create a file called jquery-cookie.js and inside do

define(["jquery"], // Require jquery
       function($){
// Put here the plugin code. 
// No need to return anything as we are augmenting the jQuery object
});
requirejs.config( {
    "shim": {
        "jquery-cookie"  : ["jquery"]
    }
} );

i wondered if i could do things like jQuery does, which is like this:

if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
    define( "jquery", [], function () { return jQuery; } );
}

or if this is the only way to make jQuery plugins compatible with requirejs or any amd

Answer

Carl Raymond picture Carl Raymond · Aug 9, 2012

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
  };
})