js模块系统详解(一)

前端涉及到的模块规范有:CommonJS、AMD、ES6的模块系统、NodeJS的模块系统。

CommonJS

nodeJS的诞生标志着”JavaScript模块化编程“的正式诞生。在浏览器环境下,没有模块化编程,倒也不是很大的问题,毕竟网页程序的复杂性有限。但是在服务端,一定要有模块,与操作系统和其他应用程序互动,否则根本没法编程。

nodejs的模块系统,就是参考commonjs规范实现的。

AMD

AMD的全称是Asynchronous Module Define,异步模块定义。

为什么AMD会诞生呢?

在有了服务端模块后,我们自然也想要客户端模块,而且最好这两个能兼容,一个模块都不用修改,在服务端和客户端可以同时运行。

但是,CommonJS有一个重大的局限,导致它不适合在浏览器环境运行。

1
2
var math = require('math);
math.add(2, 3);

看上面的代码,乍一看似乎没有什么问题。但实际上,第二行代码需要在第一行代码执行后,才能执行。因此必须要等到math.js加载完成后。如果math.js加载时间很长,整个应用就卡在这里了。

这对于服务端编程并不是一个问题,因为服务端所有的模块都放在本地硬盘,可以同步加载完成,等待时间就是硬盘的读取时间。但是对于浏览器,这却是一个大问题,因为模块都放在服务器端,等待时取决于网速,可能要等很长时间。

因此,浏览器的模块,不能采用”同步加载”,而是要异步加载,因此AMD就诞生了。

AMD

AMD也是采用require语句,但是语法与CommonJS不同。

1
require([module], callback);

其中,第一个参数[module]是所有依赖的模块,是一个数组;第二个参数callback,则是加载成功之后的回调。

上面的那个代码,如果用AMD实现,则是:

1
2
3
require(['math'], function() {
math.add(2, 3);
});

math.add()与math模块加载不是同步的,浏览器不会发生假死。所以很显然,AMD比较适合浏览器环境。

参考:

http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html

ES6的模块系统

ES6实现了模块规范,完全可以取代CommonJS和AMD,成为服务器和浏览器通用的模块解决方案。

ES6的设计思想

设计思想是:尽量的静态化,也就是编译时加载(静态加载)。

这样在编译时就能确定模块之间的依赖关系、输入和输出的变量。

而CommonJS和AMD只能在运行时才能确定这些东西(运行时加载)(此处可以详看阮一峰的es6模块系统)。

NodeJS的模块系统