CommonJS, AMD, CMD的区别
CommonJS, AMD, CMD都是JS模块化的规范。
CommonJS是服务器端js模块化的规范,NodeJS是这种规范的实现。
AMD(异步模块定义)和CMD(通用模块定义)都是浏览器端js模块化的规范。RequireJS 遵循的是 AMD,SeaJS 遵循的是 CMD
CommonJS(同步模块定义)
一个单独的文件就是一个模块
加载模块使用require方法,该方法读取一个文件并执行,最后返回文件内部的exports对象
所以,定义一个模块就是写一个新的js文件,但是最后要将文件的内容exports出来
- 如何定义模块和加载模块?
1 | //定义一个module.js文件 |
2 | var A = function() { |
3 | console.log('我是定义的模块'); |
4 | } |
5 | /* |
6 | * 导出这个模块 |
7 | * 1.第一种返回方式 module.exports = A; |
8 | * 2.第二种返回方式 module.exports.test = A |
9 | * 3.第三种返回方式 exports.test = A; |
10 | * 注意:module.exports导出方式 与 exports导出方式是有区别的 |
11 | * 具体区别详见其他文章 |
12 | */ |
13 | exports.test = A; |
14 | |
15 | //再写一个dome.js文件,导入刚才定义好的模块 |
16 | const module = require("./module"); //加载这个模块 require中是导入模块的路径 前面的变量名自定义 代表的是导入模块所导出的对象 |
17 | |
18 | /* 调用这个模块,不同的返回方式用不同的方式调用 |
19 | * 1.第一种调用方式 module(); |
20 | * 2.第二种调用方式 module.test(); |
21 | */ |
22 | module.test(); |
23 | |
24 | |
25 | /* |
26 | * 接下来我们去执行这个文件,前提是你本地要安装node.js |
27 | * 首先打开cmd, cd到这个文件所在的目录下,执行: node dome.js |
28 | */ |
29 | node dome.js |
30 | //输出结果:我是定义的模块 |
以上就是CommonJS规范下的模块定义与加载的形式
注意: CommonJS 加载模块是同步的,所以只有加载完成才能执行后面的操作
因此 -> 像Node.js比较适用CommonJS的原因在于:Node.js主要用于服务器的编程,加载的模块文件一般都已经存在本地硬盘,所以加载起来比较快,不用考虑异步加载的方式
而 -> 浏览器环境 则 不适合适用CommonJS,原因在于浏览器环境要从服务器加载模块,这是就必须采用异步模式。所以就有了 AMD CMD 解决方案
AMD(异步模块定义)**
AMD规范通过define方法去定义模块,通过require方法去加载模块。RequireJS实现了这种规范
AMD只有一个接口:define(id?,dependencies?,factory); 它要在声明模块的时候制定所有的依赖(dep),并且还要当做形参传到factory中。要是没什么依赖,就定义简单的模块(或者叫独立的模块
1 | //编写一个module1.js文件 |
2 | //定义独立的模块 |
3 | define({ |
4 | methodA: function() { |
5 | console.log('我是module1的methodA'); |
6 | }, |
7 | methodB: function() { |
8 | console.log('我是module1的methodB'); |
9 | } |
10 | }); |
11 | |
12 | //编写一个module2.js文件 |
13 | //另一种定义独立模块的方式 |
14 | define(function () { |
15 | return { |
16 | methodA: function() { |
17 | console.log('我是module2的methodA'); |
18 | }, |
19 | methodB: function() { |
20 | console.log('我是module2的methodB'); |
21 | } |
22 | }; |
23 | }); |
24 | |
25 | //编写一个module3.js文件 |
26 | //定义非独立的模块(这个模块依赖其他模块) |
27 | define(['module1', 'module2'], function(m1, m2) { |
28 | return { |
29 | methodC: function() { |
30 | m1.methodA(); |
31 | m2.methodB(); |
32 | } |
33 | }; |
34 | |
35 | }); |
36 | |
37 | //再定义一个main.js,去加载这些个模块 |
38 | require(['module3'], function(m3){ |
39 | m3.methodC(); |
40 | }); |
41 | |
42 | //我们在一个html文件中去通过RequireJS加载这个main.js |
43 | //等号右边的main指的main.js |
44 | <script data-main="main" src="require.js"></script> |
45 | |
46 | //浏览器控制台输出结果 |
47 | 我是module1的methodA |
48 | 我是module2的methodB |
CMD(通用模块定义)
CMD是SeaJS 在推广过程中对模块定义的规范化产出
AMD和CMD的区别:
- 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible(尽可能的懒加载,也称为延迟加载,即在需要的时候才加载)。
- CMD 推崇依赖就近,AMD 推崇依赖前置。虽然 AMD 也支持 CMD 的写法,同时还支持将 require 作为依赖项传递,但 RequireJS 的作者默认是最喜欢上面的写法,也是官方文档里默认的模块定义写法。
- AMD 的 API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。比如 AMD 里,require 分全局 require 和局部 require,都叫 require。CMD 里,没有全局 require,而是根据模块系统的完备性,提供 seajs.use 来实现模块系统的加载启动。CMD 里,每个 API 都简单纯粹。
注意:部分文章可能会在不就的将来更新
如果能够帮助到你,是小编最大的荣幸
当然 有 不好的地方 请大家帮忙指出 学习永无止境
小编一直认为 人外有人 天外有天 一起学习 共同进步
让我们共同加油吧!!!
原文作者: Yunjie Ge
原文链接: http://www.blog.geyunjie.com/2018/08/15/amdcmdcom/
版权声明: 转载请注明出处(必须保留作者署名及链接)