RequireJS shim configuration, jQuery plugins and enforceDefine

If you’re using RequireJS’s shim configuration to load jQuery plugins while setting enforceDefine: true in your configuration, you probably noticed the following uncaught error in your JavaScript console: (The following example is for the iCheck plugin)

Uncaught Error: No define call for iCheck
http://requirejs.org/docs/errors.html#nodefine

Reading the documentation at that URL, yields the following important tidbit. (Emphasis mine)

This occurs when enforceDefine is set to true, and a script that is loaded either:

Did not call define() to declare a module.
Or was part of a shim config that specified a string exports property that can be checked to verify loading, and that check failed.
Or was part of a shim config that did not set a string value for the exports config option.

This means if you have probably defined your shim config like so, because you technically don’t need any exports from a jQuery plugin: (Since they just extend the jQuery object)

 shim: {
    "iCheck": ["jquery"],
  },

This doesn’t define an exports, so that is the cause of the error. To fix this, you can simply define the export to be the function the plugin adds to the jQuery object:

  shim: {
    "iCheck": {
      deps: ["jquery"],
      exports: "jQuery.fn.iCheck",
    }
  },

You can then reference the shim configured module (in this case, iCheck) using a requirejs() or define() call.

4 Comments »

  1. In your example for iCheck you set the exports equal to the function added to the jQuery object… how would you go about handling this for a plugin that adds 10+ methods, e.g. jquery-ui?

  2. @Josh,

    It’s not perfect, but if you can see which function is added last (hopefully this is done in a deterministic fashion), exports can be set to this last one to ensure that everything’s loaded for the plugin.

  3. Thanks Peter,

    So just read through the plugin code to see what’s added last eh?

  4. @Josh, yes, that’s the idea. Definitely a bit of a kludge. For this reason I’m starting to look at Browserify instead of RequireJS.

    Basically, it uses a CommonJS-module format and requires a build to bundle up all the modules into a single file before deployment (so it’s not done client-side as with RequireJS), but the end result may be easier development.

    Check this out: http://esa-matti.suuronen.org/blog/2013/03/22/journey-from-requirejs-to-browserify/

Comments are now closed for this entry.