0%

前端模块化

目前JS模块化规范主要三种:浏览器端的 AMDCMD 规范。经常被 exports、modules.exports、export、require 绕懵,遂来探一探究竟。

AMD规范 (requireJS) 浏览器端 异步加载模块 提前执行

AMD (Asynchronous Module Definition): 在浏览器中使用,并用 define 函数定义模块,用require引入模块;
它是 RequireJS 在推广过程中对模块定义的规范化产出,诣在帮开发者解决各个 js 文件的依赖问题,让开发者在页面引入多个 js 时,不必考虑各个 js 的依赖关系。

CMD规范 (SeaJS) 浏览器端 异步加载模块 延迟执行

CMD (Common Module Definition): 在浏览器端使用,使用 define 函数定义模块,用 module.exports 暴露模块;
它 是SeaJS 在推广过程中对模块定义的规范化产出。与 AMD 也都是异步加载模块,只是依赖加载的时间点不一样。相比于 AMD 依赖前置,CDM 加载采用就近原则(个人理解:先依赖,先加载)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
define(function(require, exports, module) {
let val = 'module4'
function getVal() {
console.log(val)
}

// 引入module2 同步
let module2 = require('./module2.js');
module2()

// 异步引入module3
require.async('./module3.js', function(module3) {
module3.module3.getData()
});

// 暴露模块
module.exports = {getVal}
})

CommonJS 服务端 同步加载模块

NodeJS 的模块机制使用的就是 commonJS 的规范,因为服务端第三方库大多已存于本地,加载速度较快,使用同步加载比较理想。它使用 module.exports 或者是 exports 来导出,使用 require 引入。

ES6 的 export 和 import 浏览器端

ESM (ES Modules) 是 JavaScript 从 ES6(ES2015) 开始支持的原生模块机制,使用importexport引入和导出模块。

UMD 通用模块机制

UMD (Universal Module Definition) 是一个通用模块的机制,它使一个模块能运行在各种环境下,不论是 CommonJS、AMD,还是非模块化的环境。代码实现原理如下:

1
2
3
4
5
6
7
8
9
if (typeof define === 'function') { // 兼容 requireJS AMD、CMD规范   
define(function () {
return moduleName;
});
} else if (typeof exports !== 'undefined') { // 兼容 webpack 引入方式(commonJS)
module.exports = moduleName;
} else {
this.moduleName = moduleName; // 普通引入,注册到全局
}

常见于打包/编译工具中:

1
2
3
4
5
6
7
8
9
10
11
12
13
function webpackConfig(BASE_PATH) {
return {
mode: 'development',
entry: {
index: path.join(__dirname, '../src/index'),
preview: path.join(__dirname, '../src/view')
},
output: {
libraryTarget: 'umd'
},
...
}
}

参考资料

前端模块化详解(完整版)
关于commonjs,AMD,CMD之间的异同