UMD is a Lie

By Ryan Florence

Occasionally I get grumpy and tweet about modules, then people reply to me with "solutions", most of which I've attempted. I'm writing this to have something to link to and avoid lengthy twitter threads :)


Hey look, there I am!

Nearly three years ago from the time of this writing, a few of us tried to provide a way for consumers of our libraries to be able to use whatever module format they wanted in their application. Three years later I realize its a sneaky lie: its just another format, but worse than any of the others.


Consider you are a library author. Most solutions people throw around are fine for applications where you have shim configs and build steps, but as a module author you don't have the same flexibility.

No Dependencies

UMD works great when you have no dependencies in your lib. This is why we start to think that UMD is a great way to write third-party code for others to consume, stuff like jQuery and moment can get away with this easily.

But, Dependencies

As soon as you go searching for a dependency, you have two choices:

  1. Find something that also supports UMD (unlikely)
  2. Build your own

At this moment, UMD becomes a brand-new module format, not an interop format. If you're going to advocate for a format, how about one that isn't ...

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['b'], function (b) {
            return (root.returnExportsGlobal = factory(b));
    } else if (typeof exports === 'object') {
        module.exports = factory(require('b'));
    } else {
        root.returnExportsGlobal = factory(root.b);
}(this, function (b) {
    return {};

... that.

Distributing to Every Format

Some say to export to everything rather than UMD. This does not solve the dependency problem. I still must only depend on modules that export to everything.

ES6 Modules

When they ship, hopefully we can all adopt them quickly. Transpiling today still leaves you with a decision on which module format(s) to target and now you're back at the beginning of this article.


SystemJS is a loader that can load all the module types from npm, cdns, etc. Its really promising. But at the moment, that requires either a smart asset server (HTTP2/SPDY) that negates the need for bundling up your code, or a prescribed bundler/loader. If we're going to be prescribing something, we still haven't achieved the interoperability goal.

If you must prescribe a loader, you might as well prescribe a format.

If You Have the Answer

If I'm wrong, please make a repository that depends on underscore and querystring that works with an application using RequireJS without a build and also an application using browserify.


A lot of people don't like Arby's. But basically, these roast beefs are p good.