模块化发展历程

模块化的发展历程经历了多个阶段,从早期的自执行函数(IIFE)到现代的 ES Module,每个阶段都在不断地解决代码组织、依赖管理和模块加载等问题。下面是模块化发展历程的简要介绍:

1. IIFE(立即执行函数):

在早期的 JavaScript 开发中,为了避免全局变量的污染和命名冲突,开发者经常使用自执行函数(Immediately Invoked Function Expression,IIFE)来创建一个独立的作用域,将代码封装起来,达到模块化的效果。但是这种方式并没有真正解决模块化的问题,只是通过作用域的隔离来减少了全局污染的风险。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 使用IIFE创建模块
(function () {
var privateVariable = "I am private";

function privateFunction() {
console.log("This is a private function");
}

// 导出公共接口
window.MyModule = {
publicMethod: function () {
console.log("This is a public method");
privateFunction();
},
};
})();

2. AMD(异步模块定义):

AMD 是由 RequireJS 提出的一种模块定义规范,它允许开发者异步加载模块,从而提高了页面的加载性能。AMD 规范定义了 define 函数用于定义模块,以及 require 函数用于加载模块。通过 AMD,开发者可以明确地声明模块之间的依赖关系,并在需要时异步加载这些依赖模块。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 使用AMD定义模块
define(["dependency1", "dependency2"], function (dependency1, dependency2) {
var privateVariable = "I am private";

function privateFunction() {
console.log("This is a private function");
}

// 导出公共接口
return {
publicMethod: function () {
console.log("This is a public method");
privateFunction();
},
};
});

3. CMD(通用模块定义):

CMD 是由 SeaJS 提出的一种模块定义规范,与 AMD 类似,但更加注重模块的延迟执行。CMD 规范定义了 define 函数用于定义模块,以及 require函数用于加载模块。相比于 AMD,CMD 更加倾向于将模块的加载放在模块内部,以便实现模块的按需加载。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 使用CMD定义模块
define(function (require, exports, module) {
var dependency1 = require("dependency1");
var dependency2 = require("dependency2");

var privateVariable = "I am private";

function privateFunction() {
console.log("This is a private function");
}

// 导出公共接口
exports.publicMethod = function () {
console.log("This is a public method");
privateFunction();
};
});

4. CommonJS:

CommonJS 是一种服务器端模块的规范,最初是为 Node.js 设计的,后来也被广泛应用于前端开发中。CommonJS 规范定义了 require 函数用于加载模块,以及 module.exportsexports 对象用于导出模块。通过 CommonJS,开发者可以在 Node.js 环境下实现模块化的开发,并使用类似于服务器端的模块加载机制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 使用CommonJS定义模块
var dependency1 = require("dependency1");
var dependency2 = require("dependency2");

var privateVariable = "I am private";

function privateFunction() {
console.log("This is a private function");
}

// 导出公共接口
module.exports = {
publicMethod: function () {
console.log("This is a public method");
privateFunction();
},
};

5. UMD(通用模块定义):

UMD 是一种通用的模块定义规范,可以兼容 AMD、CMD 和 CommonJS 等多种模块加载机制。UMD 模块可以在浏览器端和 Node.js 环境下通用,使得开发者可以更灵活地选择适合自己项目的模块加载方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 使用UMD定义模块
(function (root, factory) {
if (typeof define === "function" && define.amd) {
// AMD
define(["dependency1", "dependency2"], factory);
} else if (typeof exports === "object") {
// CommonJS
module.exports = factory(require("dependency1"), require("dependency2"));
} else {
// 浏览器全局变量
root.MyModule = factory(root.dependency1, root.dependency2);
}
})(this, function (dependency1, dependency2) {
var privateVariable = "I am private";

function privateFunction() {
console.log("This is a private function");
}

// 导出公共接口
return {
publicMethod: function () {
console.log("This is a public method");
privateFunction();
},
};
});

6. webpack(require.ensure):

webpack 是一种现代化的模块打包工具,它支持多种模块化的规范,包括 CommonJS、AMD、ES Module 等。在 webpack 中,开发者可以使用 require.ensure 来实现按需加载模块,从而提高页面的加载性能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 在需要时动态加载模块
function loadModule() {
require.ensure(["./module"], function (require) {
var module = require("./module");
module.doSomething();
});
}

// 主程序入口
function main() {
// 加载模块
loadModule();
}

// 启动主程序
main();

7. ES Module:

ES Module 是 JavaScript 的官方模块化规范,从 ES6 开始被纳入到 JavaScript 的标准中。ES Module 允许开发者使用 importexport 语法来定义和导出模块,从而实现了原生的模块化开发。ES Module 在浏览器和 Node.js 环境下都得到了广泛的支持,并成为了现代 JavaScript 开发的主流模块化方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 使用ES Module定义模块
import dependency1 from "dependency1";
import dependency2 from "dependency2";

var privateVariable = "I am private";

function privateFunction() {
console.log("This is a private function");
}

// 导出公共接口
export function publicMethod() {
console.log("This is a public method");
privateFunction();
}

8. <script type="module">

HTML 的<script type="module">标签是浏览器原生支持的 ES Module 的加载方式。通过在 HTML 中直接使用这个标签,开发者可以加载并执行 ES Module,从而实现了在浏览器端的模块化开发。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ES Module Example</title>
</head>
<body>
<!-- 使用ES Module加载模块 -->
<script type="module">
import { publicMethod } from "./module.js";

publicMethod();
</script>
</body>
</html>