CommonJS 与 ES Module

Youky ... 2021-10-11 前端
  • 前端工程化
About 2 min

# CommonJS 与 ES Module

# 模块化方案要解决的问题

  • JS 文件的组织和维护问题
  • 私有空间问题
  • 作用域污染问题
  • 理清管理模块间的依赖关系

# CommonJS

CommonJS 是一种社区提出的规范。以同步阻塞的方式加载模块

# 导出

导出一个对象

module.exports = {
  key: value,
};
1
2
3

可以导出单独的属性

module.exports.key = value;
1

此时可以省略 module

exports.key = value;
1

省略 module 时,在用 exports 导出单个变量后,就无法在导出整个对象了

exports.key = value;
exports.key2 = value2;
module.exports = {
  key3: value3,
};
// 只导出了key1和key2
1
2
3
4
5
6

# 导入

导入的值是其原始值的拷贝,可以对其进行修改。

const { value } = require("./module.js");
const { value } = require("./module.js"); // 重复的导入会被忽略
value = "newValue"; // 修改不会改变原始值
1
2
3

# 缓存机制

为了防止多次导入使模块反复执行带来的问题,CommonJS 提供了缓存机制。

以模块绝对路径为 key,module 对象为 value 写入 cache 缓存。在引入模块时,会首先判断模块是否在 cache 内,若在则直接返回。

// foo.js
module.exports = {
  foo: 1,
};

// bar.js

const foo = require("./foo");
foo.foo = 2;

const foo2 = require("./foo");
console.log(foo2.foo); // 2
console.log(foo == foo2); // true
1
2
3
4
5
6
7
8
9
10
11
12
13

# ES Module

在 ES6 中官方支持的模块系统。会在程序开始前先根据依赖关系找到所有模块,生成一个无环关系图

# 导出

在导出时定义:

export let value = 1;
1

定义后一起导出:

const v = 1;
const func = function() {
  ++v;
};
export { v, func };
1
2
3
4
5

# 导入

ES Module 的 import 导入是静态的,必须放在文件的开头。

导入的是原本值的引用。

import { v, func } from "./module.js";
func();
console.log(v); // 2
1
2
3

# 二者区别

  • CommonJS 的导入是动态的运行时导入,ESModule 的导入是静态的编译时导入(ES2020 新加了动态 import 函数)
  • CommonJS 导入的值是原始值的拷贝,可以修改。ESModule 导入的值是存在映射关系的引用,不可修改
  • 使用混合导出的语法时,CommonJS 会出现覆盖问题,而 ESModule 不会
  • 兼容性:CommonJS 兼容性更好

# 为什么开发中两种方式可以混用

ESModule 会被打包工具处理为 CommonJS

Last update: October 16, 2022 21:28
Contributors: youky7 , Youky