Why Modular JavaScript Matters: From Script Tags to ES Modules

This article explains the need for JavaScript modularization, compares major module standards such as CommonJS, AMD, CMD, UMD and ES Modules, and traces their historical evolution, highlighting benefits, drawbacks, and practical usage examples for modern front‑end development.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Why Modular JavaScript Matters: From Script Tags to ES Modules

1. Why Modularization Is Needed

Before modules, developers loaded each file with <script src="module1.js"></script> and exposed APIs on the global window object. As projects grew, global variable conflicts and maintenance difficulties increased.

Modularization brings several advantages:

Reduces global variable pollution

Controls dependencies

Improves code maintainability

Increases code reuse

Practices divide‑and‑conquer thinking

2. Current Module Standards

CommonJS

Specification

Module identifiers follow a naming rule

Use require(dependency) to load other modules

Dependencies are loaded recursively

Failed loads throw an exception

Exports are assigned to module.exports, which must be an object

Usage

// math.js
var num = 0;
function add(a, b) {
  return a + b;
}
module.exports = {
  num: num,
  add: add
};

Loading the module:

// Load custom module (path can omit .js)
var math = require('./math');
math.add(1, 2); // => 3

Pros

Simple and easy to use

Handles module dependencies

Reduces global variable pollution

Cons

Cannot run directly in browsers

Does not support non‑blocking parallel loading

AMD (Async Module Definition)

Represented by RequireJS.

Specification

Module identifiers follow CommonJS module identifiers

Define modules with define(id, dependencies, factory) If dependencies includes require, exports or module, behavior matches CommonJS

Omitting dependencies defaults to ['require','exports','module'] Factory can return any value or assign to exports / module.exports Usage

define({
  method1: function() {},
  method2: function() {}
});

// With dependencies
define([
  'module1',
  'module2'
], function (m1, m2) {
  // ...
});

require(['foo', 'bar'], function (foo, bar) {
  foo.doSomething();
});

Pros

Works in browsers

Supports asynchronous loading

Allows parallel loading of multiple modules

Cons

Increases development cost

Loads all dependencies up‑front rather than on demand

CMD (Common Module Definition)

Popularized by Sea.js.

Usage

define(function (require, exports, module) {
  var add = function (a, b) {
    return a + b;
  };
  exports.add = add;
});

seajs.use(['math.js'], function (math) {
  var sum = math.add(1, 2);
});

Pros

Enables module loading in browsers

Supports on‑demand loading

Dependencies are resolved locally and execution is delayed

Cons

Relies on Sea.js packaging, adding complexity to the loading logic

UMD (Universal Module Definition)

Combines CommonJS and AMD. Loading order:

If exports exists, use CommonJS

Else if define exists, use AMD

Otherwise, fall back to a global variable or throw an error

ES Module

Usage

// Export
export function hello() {};
export default {
  // ...
};

// Import
import { readFile } from 'fs';
import React from 'react';

Pros

Native syntax support, simple to use

Cons

Not fully supported in all browsers without transpilation to ES5

Browser support chart

3. Evolution History of Module Systems

2009: Mozilla engineers created the ServerJS standard (later renamed CommonJS) for server‑side modularization.

Later in 2009, Node.js emerged; npm adopted the CommonJS format, bringing it to front‑end developers.

Three main schools debated new standards:

Conservative : Convert server‑side modules for browsers using tools like Browserify.

Radical : Use asynchronous callbacks (AMD) to suit browser characteristics.

Middle : Retain useful CommonJS features while adding enhancements.

Key milestones:

2009: James Burke created RequireJS; 2011 AMD formed.

2011: Alibaba’s Yu Bo introduced Sea.js and the CMD spec.

2014: Homa Wong released the first UMD implementation.

2016: ES6 (ES Module) was standardized; 2017 Chrome 61 added native support.

These developments paved the way for modern bundlers like Vite that leverage native ES Modules.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

frontendJavaScriptModule SystemCommonJSESMAMD
Tencent IMWeb Frontend Team
Written by

Tencent IMWeb Frontend Team

IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.