logo头像
Snippet 博客主题

前端各加载方式解析

本文于1019天之前发表,文中内容可能已经过时。

Commonjs

  • 同步加载,主要用于服务端,node采用了这个规范,第一次require(‘xx’)的时候会执行整个文件,然后在内存中生产一个对象,之后再次用到这个模块,就会自动到exports属性中取值,不会再次执行该模块,也就是说直接从缓存中取值
1
2
3
4
5
6
// 第一次加载后内存中的结构
{
id: 'xx', // 模块名
exports: {}, // 该模块中导出的接口
loaded: true // 判断模块是否已经被加载完毕
}
1
2
3
4
5
6
7
8
9
// demo
// math.js
exports.add = function(a, b){
return a + b
}
// index.js
const math = require('math')
math.add(2, 3)

AMD

  • 异步定义模块,异步加载,也就是说加载模块的时候不会影响到后面语句的执行,需要注意的是一个模块依赖多个模块时候,依赖的这多个模块是同步加载的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// math.js
require(function(){
var add = function(x, y){
return x + y
}
return {
add: add
}
})
// index.js
require(['math'], function(math){
math.add(2, 3)
})

CMD

  • 和AMD类似,但是AMD是依赖前置,预先加载依赖,而CMD是依赖就近,延迟执行
1
2
3
4
5
6
7
// CMD
define(function(require, exports, module) {
var a = require('./a');
a.doSomething();
var b = require('./b');
b.doSomething();
})
1
2
3
4
5
// AMD
define(['a', 'b'], function(a, b) {
a.doSomething();
b.doSomething();
})

UMD

  • 兼容了Common AMD CMD
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node, CommonJS之类的
module.exports = factory(require('jquery'));
} else {
// 浏览器全局变量(root 即 window)
root.returnExports = factory(root.jQuery);
}
}(this, function ($) {
// 方法
function myFunc(){};
// 暴露公共方法
return myFunc;
}));

es6

  • 静态分析模块依赖, Commonjs是模块的复制,而es6则是模块的引用
1
2
3
4
5
6
7
8
// math.js
export const add = function(x, y){
return x + y
}
// index.js
import {add} from 'math.js'
console.log(add(3, 4))

相互依赖的包怎么执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// a.js
import { bar } from './b.js'
console.log('a模块正在加载中')
console.log('b模块的输出是', bar)
export const foo = 'foo'
// b.js
import { foo } from './a'
console.log('b模块正在加载中')
console.log('a模块的输出是:', foo)
export const bar = 'bar'
// 调用a.js输入内容如下
b模块正在加载中
a模块的输出是: undefined
a模块正在加载中
b模块的输出是 bar