A Review of Frontend Moduleization Development and Tooling
This article reviews the evolution of frontend moduleization over the past decade, discusses the problems of early script inclusion, presents various solutions such as namespaces, closures, CommonJS, ES6 modules, and modern build tools, and illustrates each approach with concrete JavaScript code examples.
1. The Days Without Moduleization
In the early days JavaScript was used only for simple form validation and basic interactions, often written directly inside server‑side templates, resulting in chaotic, monolithic scripts.
2. Traditional Moduleization
As AJAX popularized, code size exploded, prompting developers to split functionality into smaller, reusable modules.
Early moduleization relied on plain JavaScript without any formal system like Require, AMD, or SeaJS, requiring developers to manually organize code.
The main goals were code reuse, clearer structure, and easier maintenance.
Example code (Example 1):
function show(element) { // display an element }
function close(element) { // hide an element }These functions would typically be placed in a utils.js file and referenced in HTML (Example 2):
<body>
<script src="lib/utils.js"></script>
<script src="lib/page-1.js"></script>
<script src="lib/page-2.js"></script>
</body>2.1 Problems
Global variable conflicts when different pages define functions with the same name.
Manual dependency management; scripts must be loaded in the correct order, which becomes complex in large projects.
2.2 Attempts to Solve the Problems
2.2.1 Code Extraction
var utils = {
_name: ‘baotong.wang’,
show: function(element) {},
close: function(element) {}
}2.2.2 Namespaces
var com.company.departure.team.utils = {};2.2.3 Closure Encapsulation (Immediately‑Invoked Function Expression)
(function() {
var Company = Company || {};
Company.Base = Company.Base || {};
var _name = ‘baotong.wang’;
function show() {}
function close() {}
Company.Base.Util = { show: show, close: close };
})();2.2.4 Dependency Management
Early solutions such as Baidu’s Tangram and Qwrap used explicit dependency arrays, but they were limited and not widely adopted.
2.3 Tools of the Era
2.3.1 Code Concatenation – merging multiple scripts into a single file to reduce HTTP requests, while keeping shared libraries separate for caching.
2.3.2 Code Minification – compressing JavaScript to improve load speed (e.g., YUI Compressor).
3. The Arrival of Node
Node.js (2009) introduced npm, enabling a rich module ecosystem and the CommonJS module format for the frontend.
3.1 CommonJS Overview
CommonJS defines a simple module system where each file has its own scope, exports are assigned to module.exports , and modules are loaded with require() .
3.2 npm Ecosystem
npm provides a central repository for reusable packages, and CommonJS natively supports locating modules in node_modules .
3.3 Node for Frontend Developers
Node’s JavaScript runtime allowed frontend engineers to write build tools (grunt, gulp, browserify, webpack) that automate module bundling and other tasks.
4. Modern Moduleization Solutions
4.1 CommonJS Details
Each file is a module with its own private scope.
The module object represents the current module.
module.exports defines the public API.
require loads another module and returns its exports .
If a module cannot be found, an error is thrown.
Example implementation:
// module.js
module.exports = {
func: function() {},
field: "string"
};
module.exports.show = function() {};
// usage
var Base = require("../base.js");
var page = require("./file.js");
page.show();4.2 Other Patterns
AMD (RequireJS) and CMD (SeaJS) provide asynchronous loading for browsers, but CommonJS remains dominant in many large Chinese companies.
4.3 Refactoring Example
Transforming the earlier closure example to CommonJS:
// module.js
var _name = 'baotong.wang';
function show() { alert(_name); }
function close() {}
module.exports = { show, close };
// page.js
var mod = require('./module.js');
mod.show();4.4 Browser Support
Since browsers do not understand require , tools like Browserify, Fekit, and YKit convert CommonJS modules into browser‑compatible bundles.
4.5 Fekit Compilation Process
Fekit is a Node‑based CLI that parses CommonJS, supports requiring CSS, and handles internal module repositories. The core wrapper generated for each module looks like:
;(function(__context) {
var module = {
id: "{{md5Key}}",
filename: "{{fileName}}",
exports: {}
};
if (!__context.____MODULES) { __context.____MODULES = {}; }
var r = (function(exports, module, global) {
// ---------- original file code ----------
{source}
// ---------- original file code ----------
})(module.exports, module, __context);
__context.____MODULES["{{md5Key}}"] = module.exports;
})(this);4.6 ES6 Modules
ES6 introduces import and export . In practice, Babel transpiles them to CommonJS ( require / module.exports ) for compatibility.
5. Summary
This article reviewed the history of frontend moduleization, highlighted early problems, described the rise of CommonJS and related tooling, and briefly mentioned ES6 module syntax, providing code snippets to illustrate each stage.
Qunar Tech Salon
Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.