理解webpack5文档中的require.cache

8 篇文章 0 订阅
1 篇文章 0 订阅

引言

webpack是基于nodejs开发的一个文件打包工具,在其5.X版本的文档中讲到模块缓存多处引用同一模块,最终只会产生一次模块执行和一次导出。所以,会在运行时(runtime)中会保存一份缓存。删除此缓存,则会产生新的模块执行和新的导出。 里面有个例子引起了我的注意,代码如下:

var d1 = require('dependency');
require('dependency') === d1; //true
delete require.cache[require.resolve('dependency')];
require('dependency') !== d1; //true
// in file.js
require.cache[module.id] === module;
require('./file.js') === module.exports;
delete require.cache[module.id];
require.cache[module.id] === undefined;
require('./file.js') !== module.exports; // in theory; in praxis this causes a stack overflow
require.cache[module.id] !== module;

分析

第一段代码,我们可以理解,nodejscommonjs模块系统,require一次模块,会进行缓存(require.cache),通过require.cache对象,我们可以获取缓存,并进行删除,下次require时会重新载入并再次缓存。

第二段代码,有点不好理解,特别是有个注释“// in theory; in praxis this causes a stack overflow”,如何理解这段代码在实际环境中会导致栈溢出呢?

我们一行一行代码进行分析:

require.cache[module.id] === module;

这个执行为true,本模块和缓存中的模块是相同的。

require(‘./file.js’) === module.exports;

这个执行为truemodule.exports就是一个commonjs模块,就是本文件导出为commonjs模块,require('./file.js')就是引入本文件自身,引入为commonjs模块,所以这两个是等价的。

delete require.cache[module.id];

删除模块缓存,这个等价于 delete require.cache[require.resolve('./file.js')]

require.cache[module.id] === undefined;

这个执行为true,那么关键就在这里,缓存失效了,下次如果遇到require就会重新载入模块,并重新缓存。

require(‘./file.js’) !== module.exports;

这就遇到了require,所以会重新加载并执行,但是执行时又会缓存失效,再次遇到require就又开始重新加载并执行,这样就构成了死循环,不断重新加载并执行require('./file.js'),而循环调用函数其实会使栈空间溢出,因为函数就是被压入栈的,不停的压入函数,最终导致溢出。这行代码其实是执行不到的,只是不断循环执行前面几行代码。

require.cache[module.id] !== module;

缓存失效,此处获取的缓存永远都不会是module自身,其实这个地方也是执行不到的。

需要注意的是:

  • 第二段代码的执行应该是通过require来执行,不是用node直接执行,即不能通过:
    node ./file.js来执行,而应该用一个文件比如node ./index.js来执行:
//index.js

require('./file.js')
  • 最新的LTS版本node16,运行后栈溢出,直接退出不会报错。
// file.js
console.log(1, require.cache[module.id] === module)
console.log(2, require('./file.js') === module.exports)
delete require.cache[module.id]
console.log(3, require.cache[module.id] === undefined)
console.log(4, module.id === require.resolve('./file.js'))
console.log(5, require.main === module)
console.log(6, require('./file.js') !== module.exports)
console.log(7, require.cache[module.id] !== module)

栈溢出自动退出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值