我很好奇是否有任何好方法在使用后卸载模块。我有些情况下我需要使用带来大量代码的模块,但很少使用它们(比如作为管理工具),但我不愿意使用它们,因为之后它们可能只是浪费内存可能会更好用于别处。是否有任何方法可以显式地卸载它们,或者允许系统在没有使用一段时间时这样做?
答案 0 :(得分:70)
是的,可以直接访问模块缓存:
var name = require.resolve('moduleName');
delete require.cache[name];
请注意,如果您的代码带有您想要删除的这些模块所公开的内容的引用,则不会将其清除。
(顺便说一句:在表面之下,require.resolve
和require.cache
只是Module._resolveFilename
和Module._cache
的代理,Module
是核心模块loader,即require('module')
。)
答案 1 :(得分:3)
您可以执行以下操作来“卸载”节点模块:
/**
* Deletes a node module and all associated children
* from node require cache
* @param {string} moduleName The name of the module or
* absolute/relative path to it
*/
function deleteModule(moduleName) {
var solvedName = require.resolve(moduleName),
nodeModule = require.cache[solvedName];
if (nodeModule) {
for (var i = 0; i < nodeModule.children.length; i++) {
var child = nodeModule.children[i];
deleteModule(child.filename);
}
delete require.cache[solvedName];
}
}
“卸载”节点模块意味着您从节点要求缓存中“删除”其条目。上面的代码片段可以从缓存和所有相关模块(子模块)中传递删除一个节点模块。
在我的情况下,我要求“index.js”,同时需要“/lib/.js”。我想测试“index.js”的初始化(因此其中唯一需要的其他模块是/lib/.js)。从缓存中删除“index.js”是不够的,因为缓存维护了对“/lib/.js”的单独引用,导致模块“/lib/.js”不再从其文件中加载。
上面的代码肯定会从缓存中删除此模块所依赖的其他模块(这实际上是我想要的但是你可能不想对其他模块这样做,比如“fs”,“path”甚至“下划线”) 。
您始终可以扩展此方法以接受您不想删除的模块列表,或者可以应用于已解析模块的“路径”的过滤器。您可以说:不要删除核心节点模块(核心节点模块名称列表可用作npm包:https://www.npmjs.com/package/node-core-module-names)或不删除node_modules等下的任何软件包等。这可能是函数内部的过滤器,但它是相同的逻辑。