1. 简介

ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。
CommonJS 和 AMD 模块,都只能在运行时确定这些东西。
比如,CommonJS 模块就是对象,输入时必须查找对象属性。

2. CommonJS 模块

1
2
3
4
5
6
7
8
// CommonJS模块
let { stat, exists, readFile } = require('fs');

// 等同于
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;

上面代码的实质是整体加载 fs 模块(即加载 fs 的所有方法),生成一个对象(_fs),然后再从这个对象上面读取 3 个方法。
这种加载称为运行时加载,因为只有运行时才能得到这个对象,导致完全没办法在编译时做静态优化

3.ES6 模块

ES6 模块不是对象,而是通过 export 命令显式指定输出的代码,再通过 import 命令输入。

1
2
// ES6模块
import { stat, exists, readFile } from 'fs';

上面代码的实质是从 fs 模块加载 3 个方法,其他方法不加载
这种加载称为编译时加载或者静态加载。
即 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高。
当然,这也导致了没法引用 ES6 模块本身,因为它不是对象。

ES 模块化的静态特性也带来了局限:

1、import依赖必须在文件顶部;
2、export导出的变量类型严格限制;
3、依赖不可以动态确定。

ES 的 export和 export default要用谁?(用export)

其一 export default导出整体对象,不利于 tree shaking;
其二 export default导出的结果可以随意命名,不利于代码管理;

4.比较 CMD/AMD/CommonJS

  1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。
    不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。

  2. AMD 推崇依赖前置,CMD 推崇依赖就近。

  3. CommonJS 是同步的(只有加载完成才能执行后面的操作),但是 CMD/AMD 是异步的

  4. webpack 对 CommonJS 、 AMD 、ES6 的语法做了兼容,最终采用的都是 CMD 规范

JS 模块化浅谈【CommonJS、AMD、CMD、UMD、ESM】

← Prev Next →