What Are CJS, AMD, UMD, ESM, System, and IIFE?

Posted on

Module formats illustrated with Rollup examples

Jennifer Fu

Pattern on a wall

Pattern on a wall

Photo by Farzad Nazifi on Unsplash.

Modern JavaScript projects need a bundler to compile small pieces of code into something larger and more complex, such as a library or application. The popular bundlers are webpack, Rollup, Parcel, RequireJS, and Browserify. They transform JavaScript code into modules that can be loaded as one bundle.

A bundle can be arranged in different formats. In this article, we are going to present real examples of the CJS, AMD, UMD, ESM, System, and IIFE formats.

This is a standard HTML file that includes a stylesheet on line 5 and a JavaScript file on line 6:

Putting all JavaScript code into one file works for a simple case. As projects scale up, we need to modularize code into independent modules with separate namespaces. In addition to better organization, modularization brings the capabilities of encapsulation, dependency management, and reusability.

This is how a bundler comes into the picture. It is needed to compile small pieces of JavaScript code, along with stylesheets and images, into something larger and more complex, such as a library or application.

How should a bundler format the bundled code as an output? There are a number of choices, and the following formats are defined by Rollup:

  • cjs (CommonJS) — Suitable for Node and other bundlers (alias: commonjs).
  • amd (Asynchronous Module Definition) — Used with module loaders like RequireJS.
  • umd (Universal Module Definition) — Works as amd, cjs, and iife all in one.
  • es – Keep the bundle as an ES module file. Suitable for other bundlers and inclusion as a

AMD was born out of CJS to support asynchronous module loading. The main difference between AMD and CJS lies in its support for asynchronous module loading. AMD is used by RequireJS, working on the browser side.

According to Wikipedia:

“AMD provides some CJS interoperability. It allows the similar exports and require() interface in the code, although its own define() interface is more basal and preferred.”

The following is a Rollup-generated file in AMD format:

We execute this file on the browser side, and it errors out with the message define is not a function (line 1).

The error can be fixed by including require.js in index.html:

UMD is designed to work everywhere — on the server side and the browser side. It attempts to offer compatibility with the most popular script loaders of the day, such as RequireJS. In many cases, it uses AMD as a base with special casing added to handle CJS compatibility. However, the compatibility adds some complexity that makes it complicated to read and write.

The following is a Rollup-generated file in UMD format:

This code works in a browser.

The static import directive can be used to bring modules into the current scope. This directive, in contrast with require and define, can only be placed at the top of a file. The dynamic import() is currently in stage 4 of the TC39 process.

The export directive, on the other hand, can be used to explicitly make items public.

The static import and export allow static analyzers to build a full tree of dependencies without running code. In addition, this sets up the foundation of tree shaking optimization. According to Wikipedia:

“Tree shaking eliminates unused functions from across the bundle by starting at the entry point and only including functions that may be executed.”

The following is a Rollup-generated file in ESM format:

We execute this file on the browser side, and it errors out with the message Uncaught SyntaxError: Unexpected token 'export' (line 45).

The error can be fixed by setting the script tag’s type to be module in index.html:

SystemJS is a universal module loader that supports CJS, AMD, and ESM modules. Rollup can bundle the code into SystemJS’s native format.

The following is a Rollup-generated file in System format:

We execute this file on the browser side, and it errors out with the message System is not defined (line 1).

Install system.js:

npm install --save-dev systemjs

The error can be fixed by including system.js in index.html:

As the module’s name suggests, IIFE is a self-executing function that is suitable for inclusion as a