nodejs模块引入问题,commonJS和ESModule区别

背景介绍

场景:server 端运行时引入一个用于配置的 js,导出一个 json 对象,并赋值给了当前运行时的一个临时变量,然后在后面的操作中对这个临时变量进行操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import settings from "./settings";

var app = express();

app.use((req, res, next) => {
req.settings = settings;
console.log(req.settings);
next();
});

app.use((req, res, next) => {
req.settings.aaa = "123";
});
// ...

app.listen(9000);

当第一次请求时 settings 中没有 aaa 这个属性,在第一次请求过程中给 req.settings 这个临时的变量修改了属性,结果在第二个请求进来时,即使没有执行到第二个中间件,发现 settings 中已经有这个值了。导致这次的请求上下文被污染了,解决方案就是将 settings 赋值时进行深拷贝:

1
2
3
4
5
app.use((req, res, next) => {
req.settings = _.cloneDeep(settings);
console.log(req.settings);
next();
});

原理介绍

commonJS ES Module
1. 基本类型:值复制,不共享
2. 应用类型:浅拷贝,共享
3. 工作空间可以修改引入的值
1. 只读导入,动态读取
2. 不可在外部修改应用,但可以调用引用中包含的方法
执行顺序 1. 检查是否有该模块的缓存
2. 如果有,则使用缓存
3. 如果没有,则执行该模块代码,并缓存
1. 检查该模块是否引入过?
2. 是,暂时认该模块为{}
3. 否,进入该模块并执行其代码(不做缓存)
import 会被提升到最先执行

相关文档:https://zhuanlan.zhihu.com/p/161015809


nodejs模块引入问题,commonJS和ESModule区别
https://www.wobushi.top/2021/nodejs模块引入问题,commonJS和ESModule区别/
作者
Pride Su
发布于
2021年5月12日
许可协议