- CommonJS规范加载模块是同步的,只有加载完成,才能执行后面的操作。
- AMD规范是非同步加载模块,允许指定回调函数。
由于Node.js主要用于服务器编程,模块文件一般都已经存在于本地硬盘,所以加载起来比较快,不用考虑非同步加载的方式,所以CommonJS规范比较适用。但是,如果是浏览器环境,要从服务器端加载模块,这时就必须采用非同步模式,因此浏览器端一般采用AMD规范。
CommonJS
规范中的module
、exports
和require
- 每个文件就是一个模块,有自己的作用域。每个模块内部,
module
变量代表当前模块,是一个对象,它的exports
属性(即module.exports
)是对外的接口。 -
module.exports
属性表示当前模块对外输出的接口,其他文件加载该模块,实际上就是读取module.exports
变量。 - 为了方便,
Node
为每个模块提供一个exports
变量,指向module.exports
。let exports = module.exports;
-
require
命令用于加载模块文件。
使用示例:
//name.js
exports.name = function(){return '李婷婷'}; //导出
//getName.js
let getName = require('name'); //引入
注:不能直接将exports
变量指向一个值,因为这样等于切断了exports
与module.exports
的联系:如下
exports = function(x){console.log(x)}
如果一个模块的对外接口,就是一个单一的值,不能使用exports
输出,只能使用module.exports
输出。
AMD/CMD规范
-
AMD
是RequireJS
在推广过程中对模块定义的规范化产出。
CMD
是SeaJS
在推广过程中对模块定义的规范化产出。 - 对于依赖的模块,
AMD
是提前执行,CMD
是延迟执行。不过RequireJS
从2.0
开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD
推崇as lazy as possible
. -
CMD
推崇依赖就近,AMD
推崇依赖前置。
//CMD
define(function(require, exports, module) {
let a = require('./a');
a.doSomething();
···
let b = require('./b'); // 依赖可以就近书写
b.doSomething();
...
})
// AMD 默认推荐的是
define(['./a', './b'], function(a, b) {
// 依赖必须一开始就写好
a.doSomething()
...
b.doSomething()
...
})
虽然AMD
也支持CMD
的写法,同时还支持将require
作为依赖项传递,但RequireJS
的作者默认是最喜欢上面的写法,也是官方文档里默认的模块定义写法。
-
AMD
的API
默认是一个当多个用,CMD
的API
严格区分,推崇职责单一。
比如AMD
里,require
分全局require
和局部require
,都叫 require。CMD
里,没有全局require
,而是根据模块系统的完备性,提供seajs.use
来实现模块系统的加载启动。CMD
里,每个API
都简单纯粹。
拓展
目前所有的引擎都还没有实现import
,在node
中使用babel
支持ES6
,也仅仅是将ES6
转码为ES5
再执行,import
语法会被转码为require
。这也是为什么在模块导出时使用module.exports
,在引入模块时使用import
仍然起效,因为本质上,import
会被转码为require
去执行。
参考文档
CommonJS规范
AMD 和 CMD 的区别有哪些?
Node中没搞明白require和import,你会被坑的很惨