在node.js文档中:

模块在第一次加载后被缓存。这意味着(除其他外)每次调用require('foo')都会得到完全相同的返回对象,如果它将解析到相同的文件。

是否有一种方法使这个缓存无效?例如,对于单元测试,我希望每个测试都在一个新鲜的对象上工作。


当前回答

下面是我对这个问题的回答,它处理如果文件有(例如)语法错误就不加载的问题

function reacquire(module) {
const fullpath  = require.resolve(module);
const backup = require.cache[fullpath];
delete require.cache[fullpath];

 try {
   const newcopy = require(module);
   console.log("reqcquired:",module,typeof newcopy);
   return newcopy;
 } catch (e) {
    console.log("Can't reqcquire",module,":",e.message);
    require.cache[fullpath] = backup;
    return backup;
 }

}

其他回答

以下两步程序对我来说非常有效。

在动态更改模型文件i-e 'mymodule.js'后,你需要先删除预编译的模型,然后使用require-reload重新加载它

Example:
        // Delete mongoose model
        delete mongoose.connection.models[thisObject.singular('mymodule')]

        // Reload model
        var reload = require('require-reload')(require);
        var entityModel = reload('./mymodule.js');

我将在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)
}

对于这个用例,重新连接非常有用,每次调用都会得到一个新实例。简单的依赖注入node.js单元测试。

Rewire为模块添加了一个特殊的setter和getter,这样您就可以修改它们的行为以进行更好的单元测试。你可能

为其他模块或全局变量(如process)注入mock 泄露私有变量 重写模块内的变量。 Rewire不会加载文件并计算内容以模拟节点的require机制。实际上,它使用节点自己的require来加载模块。因此,您的模块在测试环境中的行为与常规情况下完全相同(除了您的修改)。

对所有咖啡因成瘾者来说,这是个好消息:重新连接也适用于Coffee-Script。注意,在这种情况下CoffeeScript需要被列在你的devDependencies中。

是的,您可以使缓存无效。

缓存存储在一个名为require的对象中。你可以根据文件名直接访问的缓存(例如- /projects/app/home/index.js而不是你会在require('./home')语句中使用的。/home)。

delete require.cache['/projects/app/home/index.js'];

我们的团队发现以下模块很有用。使某些模块组无效。

https://www.npmjs.com/package/node-resource

是的,您可以通过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的设计初衷并不是为了阻止用户做愚蠢的事情 这也会阻止他们做一些聪明的事情。”——道格·格温

我认为应该有一种方法来执行显式的非缓存模块加载。