在node.js文档中:
模块在第一次加载后被缓存。这意味着(除其他外)每次调用require('foo')都会得到完全相同的返回对象,如果它将解析到相同的文件。
是否有一种方法使这个缓存无效?例如,对于单元测试,我希望每个测试都在一个新鲜的对象上工作。
在node.js文档中:
模块在第一次加载后被缓存。这意味着(除其他外)每次调用require('foo')都会得到完全相同的返回对象,如果它将解析到相同的文件。
是否有一种方法使这个缓存无效?例如,对于单元测试,我希望每个测试都在一个新鲜的对象上工作。
当前回答
是的,您可以通过require访问缓存。缓存[moduleName],其中moduleName是你想要访问的模块名。通过调用delete require删除一个条目。cache[moduleName]将导致require加载实际文件。
这是删除与模块相关的所有缓存文件的方法:
/**
* Removes a module from the cache
*/
function purgeCache(moduleName) {
// Traverse the cache looking for the files
// loaded by the specified module name
searchCache(moduleName, function (mod) {
delete require.cache[mod.id];
});
// Remove cached paths to the module.
// Thanks to @bentael for pointing this out.
Object.keys(module.constructor._pathCache).forEach(function(cacheKey) {
if (cacheKey.indexOf(moduleName)>0) {
delete module.constructor._pathCache[cacheKey];
}
});
};
/**
* Traverses the cache to search for all the cached
* files of the specified module name
*/
function searchCache(moduleName, callback) {
// Resolve the module identified by the specified name
var mod = require.resolve(moduleName);
// Check if the module has been resolved and found within
// the cache
if (mod && ((mod = require.cache[mod]) !== undefined)) {
// Recursively go over the results
(function traverse(mod) {
// Go over each of the module's children and
// traverse them
mod.children.forEach(function (child) {
traverse(child);
});
// Call the specified callback providing the
// found cached module
callback(mod);
}(mod));
}
};
用法如下:
// Load the package
var mypackage = require('./mypackage');
// Purge the package from cache
purgeCache('./mypackage');
因为这段代码使用了相同的解析器require does,所以只需要为require指定所需的内容。
Unix的设计初衷并不是为了阻止用户做愚蠢的事情 这也会阻止他们做一些聪明的事情。”——道格·格温
我认为应该有一种方法来执行显式的非缓存模块加载。
其他回答
我做了一个小模块来删除加载后缓存中的模块。这将强制在下次需要该模块时重新计算它。参见https://github.com/bahmutov/require-and-forget
// random.js
module.exports = Math.random()
const forget = require('require-and-forget')
const r1 = forget('./random')
const r2 = forget('./random')
// r1 and r2 will be different
// "random.js" will not be stored in the require.cache
PS:你也可以把“自毁”放入模块本身。参见https://github.com/bahmutov/unload-me
PSS:更多的技巧与节点需要在我的https://glebbahmutov.com/blog/hacking-node-require/
如果你想让一个模块永远不被缓存(有时对开发有用,但记得在完成时删除它!),你可以把delete require.cache[module.id];在模块内部。
是的,您可以通过require访问缓存。缓存[moduleName],其中moduleName是你想要访问的模块名。通过调用delete require删除一个条目。cache[moduleName]将导致require加载实际文件。
这是删除与模块相关的所有缓存文件的方法:
/**
* Removes a module from the cache
*/
function purgeCache(moduleName) {
// Traverse the cache looking for the files
// loaded by the specified module name
searchCache(moduleName, function (mod) {
delete require.cache[mod.id];
});
// Remove cached paths to the module.
// Thanks to @bentael for pointing this out.
Object.keys(module.constructor._pathCache).forEach(function(cacheKey) {
if (cacheKey.indexOf(moduleName)>0) {
delete module.constructor._pathCache[cacheKey];
}
});
};
/**
* Traverses the cache to search for all the cached
* files of the specified module name
*/
function searchCache(moduleName, callback) {
// Resolve the module identified by the specified name
var mod = require.resolve(moduleName);
// Check if the module has been resolved and found within
// the cache
if (mod && ((mod = require.cache[mod]) !== undefined)) {
// Recursively go over the results
(function traverse(mod) {
// Go over each of the module's children and
// traverse them
mod.children.forEach(function (child) {
traverse(child);
});
// Call the specified callback providing the
// found cached module
callback(mod);
}(mod));
}
};
用法如下:
// Load the package
var mypackage = require('./mypackage');
// Purge the package from cache
purgeCache('./mypackage');
因为这段代码使用了相同的解析器require does,所以只需要为require指定所需的内容。
Unix的设计初衷并不是为了阻止用户做愚蠢的事情 这也会阻止他们做一些聪明的事情。”——道格·格温
我认为应该有一种方法来执行显式的非缓存模块加载。
我将在luff的答案中再添加一行并更改参数名称:
function requireCached(_module){
var l = module.children.length;
for (var i = 0; i < l; i++)
{
if (module.children[i].id === require.resolve(_module))
{
module.children.splice(i, 1);
break;
}
}
delete require.cache[require.resolve(_module)];
return require(_module)
}
我不能在回答的注释中整齐地添加代码。但我会使用@Ben Barkay的答案,然后将其添加到require中。uncache函数。
// see https://github.com/joyent/node/issues/8266
// use in it in @Ben Barkay's require.uncache function or along with it. whatever
Object.keys(module.constructor._pathCache).forEach(function(cacheKey) {
if ( cacheKey.indexOf(moduleName) > -1 ) {
delete module.constructor._pathCache[ cacheKey ];
}
});
假设您需要一个模块,然后卸载它,然后重新安装相同的模块,但使用了不同的版本,其包中有不同的主脚本。json,下一个require将失败,因为主脚本不存在,因为它缓存在Module._pathCache中