What is the Universal Module Definition (UMD)?
Asked Answered
B

1

7

I've found the(?) github repository for UMD and it comes with this description (emphasis mine):

UMD (Universal Module Definition) patterns for JavaScript modules that work everywhere.

...

This repository formalizes the design and implementation of the Universal Module Definition (UMD) API for JavaScript modules. These are modules which are capable of working everywhere, be it in the client, on the server or elsewhere.

So far, this is straightforward. At least I think it is. Node.JS uses CommonJS by default. The browser uses globals by default. I think it's saying UMD works regardless of your module system; you can build your project once instead of once per module system.

But everything that follows confuses me:

The UMD pattern typically attempts to offer compatibility with the most popular script loaders of the day (e.g RequireJS amongst others)...

Doesn't this contradict the previous paragraph? Does UMD work everywhere or just in the most popular environments?

It goes on to list at least nine "variations" to choose from. Why would there be any variations if this is meant to be universal? How do I determine which one is right for my situation?

The readme is written as though I already know the answers to these questions, but I'm trying to learn what UMD is for and when to use it.


Note: This similar question is asking about other module systems, but not UMD.

Billfish answered 12/10, 2023 at 20:55 Comment(6)
“How do I determine which one is right for my situation?” Rule of thumb: UMD is not right for your situation. Just use ES modules nowadays; you can bundle them into anything. (As for why the variations: that’s described in the same README beside each variation. The code linked in each one is just a short pattern of plain JavaScript – read it and consider how it interacts with each module system.)Thordis
The last change was 6 years ago. Regarding web technologies this is a signal that this information is outdated.Circumbendibus
@Thordis As for why the variations: that’s described in the same README beside each variation. You mean like, "amdWeb.js - Defines a module that works with AMD and browser globals?" I read that as a "what" the variation does and maybe "when" to use it. But I still don't know "why" it exists (I wrote my best guess between the two quotes). "Why" isn't there a single variation that works for everything? What part of this is Universal?Billfish
@Thordis I'll take your Rule of thumb to heart. Unfortunately, an old library in my project uses UMD and I'm trying to troubleshoot it. I don't understand why people used it in the past: what did they lose by not using it?Billfish
@Thordis Your ES modules will most likely be bundled to UMD, though :-)Schaeffer
@Schaeffer Exactly. I'm troubleshooting the built index.js file of one such library. I found an open feature request about using the lib in Node.JS (it only works in the browser ATM), and the author said it should be easy to tweak the UMD. I was trying to figure out what UMD was so I could potentially submit a PR, but I only found information that assumed you already knew what UMD was.Billfish
S
15

The repository aims to formalize the definition of universal modules. It does not provide a universal definition. The standard was written at the time because everyone defined their universal modules differently - there were some common approaches, with varying support for different environments, but nothing really established.

A universal module, as you already quoted, works in multiple environments. Before universal modules, libraries would distribute separate files for the different environments, e.g. library.amd.js, library.common.js and library.global.js. This was a major hassle for maintainers, since it required the usage of a build tool (which JavaScript does did generally not need) and extra documentation. So the aim was to define a universal module, a single file, which was all that was needed for the author to write and distribute and for the user to (down)load. Notice this was before package managers and repositories were common (or: when they started to become more popular, and you had to change your library into a module to support them).

Yet, there were still variations. Modules written for web browsers did not need to consider supporting the commonjs format, as they wouldn't work in nodejs anyway. Modules that had no dependencies wouldn't need a UMD pattern that supported require. Modules that did not use circular dependencies wouldn't need a pattern that supports a mutable exports object. You can find the explanation of these differences, and their trade-offs, in the comments documenting the patterns in the UMD repository. A library author could go there, read through them, and pick the right one.


Of course, all of that is history. Today, build tools are ubiquitous. You write your code as modern ES modules, and let your bundler figure out the rest. For library authors, you can just distribute your package as a bundle of esm files.

However, for frontend libraries, you still offer a single file for convenience, that users can download (from a CDN) and directly embed in their web pages. This still commonly employs a UMD pattern, it's just no longer written/copied by the library author into their source code, but added automatically by the transpiler/bundler.

And similarly, for backend/universal libraries that are supposed to work in node.js, you still also distribute a commonjs module build via npm to support all the users who still use a legacy version of node.js (and don't want/need to employ a transpiler themselves). This is less common nowadays for new libraries, but existing ones try hard to stay backwards-compatible and not cause applications to break.

Schaeffer answered 13/10, 2023 at 0:52 Comment(3)
Thank you so much for taking my question seriously and for your clear explanation. This was exactly what I was looking for! Serious question: would you mind if I submitted your answer as a PR to the repo's README file? The way it's currently written seems to assume everybody already knows this.Billfish
@DanielKaplan Sure, go ahead, that's what CreativeCommons is for. (Please link this answer and attribute it to @bergus from the PR description, you don't need to put anything into the README itself)Schaeffer
Done: github.com/umdjs/umd/pull/144 Thanks again!Billfish

© 2022 - 2024 — McMap. All rights reserved.