Mastering Front-End Module Systems: From IIFE to ES6 Modules
This article provides a comprehensive overview of front‑end modularization, covering the definition of modules, the evolution from early script tags through AMD/CMD to CommonJS and ES6, and explains why modern module syntax enables better dependency management and tree‑shaking.
Front-End Modularity Overview
Introduction
This article discusses front‑end modularization, focusing on what modularity is, why it is needed, the pros and cons of various module specifications, and the historical evolution of these specifications to give readers a clearer understanding of modular programming.
What Is Modularity?
A module is a portion of code packaged according to certain rules, forming a dependency relationship with other modules. Internally defined modules belong to the project, while external packages imported from npm are considered external modules.
Management of External Modules
In 2009 Node.js extended JavaScript to the backend, and a year later npm (Node Package Manager) revolutionized how external modules are used.
Using External Modules Before npm
Before npm, developers had to download library files manually and include them via <script> tags, which was inconvenient, lacked version management, and made tracking sources difficult.
Using External Modules After npm
npm provides a remote JavaScript repository; developers can install packages with npm install <module-name>, which stores them in a node_modules directory and updates package.json with version information.
Management of Internal Modules
The article then focuses on internal module management, from native JavaScript patterns (IIFE) to specifications such as CommonJS, AMD, and finally ES6.
Native JavaScript Organization
Function Pattern
function plusOne() {
// ...
}
function minusOne() {
// ...
}This approach pollutes the global namespace, leading to naming conflicts and unclear dependencies.
Object Pattern
var calculator = {
plusOne() {
// ...
},
minusOne() {
// ...
}
};While reducing global variables, the object pattern still exposes internal data to external modification.
IIFE Pattern
var calculator = (function(){
var count = 0;
function plusOne(){ count++; }
function minusOne(){ count--; }
function printCount(){ console.log(count); }
return { plusOne, minusOne, printCount };
})();
calculator.plusOne();
calculator.printCount(); // 1The IIFE creates a private scope, exposing only the public API.
Global Object Exposure (e.g., jQuery)
(function(window){
// ...
window.jQuery = window.$ = jQuery;
})(window);Relying on global objects can cause maintenance issues as projects grow.
Modular Specifications
Various specifications emerged to solve the problems of native script organization.
AMD & CMD
Older specifications like AMD (Asynchronous Module Definition) and CMD (Common Module Definition) are now largely deprecated.
define : defines a module
require : uses a module
Typical tools: RequireJS (AMD) and Sea.js (CMD).
CommonJS
CommonJS is the module system used by Node.js. Each file is treated as an independent module, wrapped in an IIFE that provides exports, require, and module objects.
(function(exports, require, module, __filename, __dirname){
// module code
});Modules export objects via module.exports and are imported with require.
const EventEmitter = require('events');
module.exports = new EventEmitter();
setTimeout(() => {
module.exports.emit('ready');
}, 1000); const a = require('./a');
a.on('ready', () => {
console.log('module "a" is ready');
});ES6 Modules
ES6 modules are designed to be static; their dependencies are known at compile time, enabling features like tree‑shaking.
Modules can only appear at the top level.
Import specifiers must be string literals.
Import bindings are immutable.
Static analysis (lexical analysis, parsing, code generation) allows tools to determine module relationships without executing code.
import foo from './foo';
import bar from './bar';Because imports are static, bundlers such as Rollup and Webpack can eliminate unused code (tree‑shaking).
Conclusion
The evolution from script tags to npm, AMD/CMD, CommonJS, and finally ES6 modules reflects the maturation of front‑end development. Modern tooling like Babel enables developers to write ES6 code while maintaining compatibility with older browsers.
References
RequireJS: https://requirejs.org/
Sea.js: https://seajs.github.io/seajs/docs/
RequireJS creates async script tags: https://github.com/requirejs/requirejs/blob/master/require.js#L1875
CommonJS specification: http://nodejs.cn/api/modules.html
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
