10

If I'm making a JavaScript library for general use, how should I handle RequireJS support?

As far as I can tell, making your code compliant with RequireJS more or less makes it impossible to use without RequireJS. So why would I do that?

  • How do people without Require use this code?

  • Is there a way to support both without forking / branching? Should I provide the shim code?

  • Do I understand this correctly?

Mims H. Wright
  • 3,049
  • 1
  • 25
  • 30
  • 1
    See [supporting both CommonJS and AMD](http://stackoverflow.com/questions/13673346/supporting-both-commonjs-and-amd) and also the source code of many common libraries such as jQuery and Knockout which support both AMD and non-AMD – explunit Jul 30 '13 at 13:40
  • UMD looks like it tries to fix every case by adding a lot of complexity. Is there a best practice that is simpler and more flexible? – Mims H. Wright Jul 30 '13 at 18:25

1 Answers1

23

If you're only dealing with browser (not node.js), it's only a handful of lines to make the library support both AMD and non-AMD.

For example, here is the file from jQuery that does it, of which all but four are comments:

// Execute the factory to produce jQuery
var jQuery = factory( window );

// Register as a named AMD module, since jQuery can be concatenated with other
// files that may use define, but not via a proper concatenation script that
// understands anonymous AMD modules. A named AMD is safest and most robust
// way to register. Lowercase jquery is used because AMD module names are
// derived from file names, and jQuery is normally delivered in a lowercase
// file name. Do this after creating the global so that if an AMD module wants
// to call noConflict to hide this version of jQuery, it will work.
if ( typeof define === "function" && define.amd ) {
    define( "jquery", [], function() {
        return jQuery;
    });
}

And a very similar snippet from Knockout can be found here:

} else if (typeof define === 'function' && define['amd']) {
    // [2] AMD anonymous module
    define(['exports'], factory);
}

Note that jQuery takes the named module approach while knockout uses an anonymous module. jQuery also leaves $ and jQuery in the global namespace, even when AMD is detected, whereas Knockout (and probably many others) do not put anything in global namespace when AMD detected. There are pros and cons to each approach, as illustrated by these questions:

Community
  • 1
  • 1
explunit
  • 18,967
  • 6
  • 69
  • 94
  • Great! So does this approach violate any rules by dirtying the global namespace with it's filthy jQuery variable? – Mims H. Wright Jul 30 '13 at 20:49
  • 1
    Note that the location of the amd export functionality has moved to a new file in [src/exports/amd.js](https://github.com/jquery/jquery/blob/master/src/exports/amd.js) – turtlemonvh Nov 19 '13 at 16:44