CommonJs & AMD & CMD & ESM
CommonJs
CommonJs
规定每个 js
文件都能被看作是一个模块, 其内部定义的变量是私有的, 不会对外暴露。不会污染全局。
CommonJs
采用同步(一个接着一个)的加载模块, 适用于服务器,不适合在浏览器端使用。
CommonJs
不被浏览器端支持, 因为浏览器没有 module, exports, require, global
四个环境变量。
如果要在浏览器使用CommonJs
, 需要使用工具转换(browserify)
主要有以下方式对模块进行导入导出:
-
module.exports = { a: 12, foo: function(){ console.log(this.a) } }
导出为一个对象
var obj = require('./m1.js')
obj.a = 34
obj.foo()
-
module.exports = function(){ return {a: 12} }
导出是一个函数, 可以直接执行
var foo = require('./m2.js')
foo()
-
exports.foo = function(){ return {a: 12}}
导出为一个对象, 对象里面的属性为foo
var obj = require('./m3.js')
obj.foo()
注意: 不是使用import
,import
是ES6
的语法
想要在浏览器环境中使用:
在index.js
中将模块导入, 然后node
使用如下命令:
browserify index.js -o bundle.js
前提是安装了browserify
这个包。
然后在html
里面引入bundle.js
AMD
不同于CommonJs
, AMD
是异步加载, 名称就是Asynchronous Module Difinition
, 允许指定回调函数, 等异步加载完成之后即可调用回调函数。
AMD
的核心思想就是通过define
来定义模块, 然后通过require
来加载模块, 它依赖于require.js
在html
文件里面引入script
<script src="require.js" data-main="./index.js"></script>
定义模块 m1:
define([模块名称], [依赖模块], function(){
name: 'vey-module-1',
getName: function(){
return name
}
return {getName: getName}
})
模块名称定义此模块的名称, 不写则默认为文件名去掉后缀
依赖模块指定此模块依赖的模块, 类型为数组。
此模块的内容定义在function
里面
再定义一个模块 m2
define(['m1'], function(m1){
name: 'vey-module-2',
function show() {
console.log(name, m1.getName())
}
return { show }
})
定义index.js
(function(){
// 配置模块的路径
require.config({
paths: {
m1: './m1'
m2: './m2'
}
})
require(['m2'], function(m2){
m2.show()
})
})()
然后就可以看到执行结果了。
AMD
是依赖前置的, 即不管你用没用到, 只要你设置了依赖, 就会去加载。不是按需加载的。
CMD
相比AMD
, CMD
也同样是异步加载, AMD
是依赖前置, CMD
是就近加载, 按需加载的。主要产物就是sea.js
核心思想与AMD
高度类似, 通过define
定义模块, require
加载模块
<script src="sea.js"></script>
<script> seajs.use('./index.js') </script>
定义 m1:
define(function (require, exports, module) {
var msg = 'm1'
function foo() {
console.log(msg);
}
module.exports = {
foo
}
})
定义 m2:
define(function (require, exports, module) {
var msg = 'm2'
function bar() {
console.log(msg);
}
module.exports = bar
})
定义 m3:
define(function (require, exports, module) {
var msg = 'm3'
function fun() {
console.log(msg);
}
exports.fun = fun
})
定义 m4:
define(function (require, exports, module) {
var msg = 'm4'
var m2 = require('./m2')
m2()
require.async('./m3', function(m3){
m3.fun()
})
function func () {
console.log(msg)
}
exports.func = func
})
定义 index.js
:
define(function (require, exports, module) {
var m1 = require('./m1')
m1.foo()
var m4 = require('./m4')
m4.func()
})
ESM
所谓ESM
, 即ECMAScript2015 Module
. 也就是ES6
中的模块化。
ES6
自带模块化, 从语言的标准上实现了模块化, 使用export
导出, import
导入。
let a = 10
let b = 20
let c = 'aaa'
export function myFun(){}
export default foo(){}
export default
默认导出, 不管是否导出其他, 这个后面跟的东西一定会被导出, 而且只能写一个默认导出
ES6 的导入导出平时用的最多, 也比较熟悉, 这里就不再啰嗦。