357
votes

From the node.js documentation:

Modules are cached after the first time they are loaded. This means (among other things) that every call to require('foo') will get exactly the same object returned, if it would resolve to the same file.

Is there a way to invalidate this cache? i.e. for unit testing, I'd like each test to be working on a fresh object.

18
Another NPM module with a watcher: npmjs.com/package/updated-requireJorge Fuentes González
It's possible to cache the file contents without using require and eval it for different scopes stackoverflow.com/questions/42376161/…lonewarrior556

18 Answers

339
votes

You can always safely delete an entry in require.cache without a problem, even when there are circular dependencies. Because when you delete, you just delete a reference to the cached module object, not the module object itself, the module object will not be GCed because in case of circular dependencies, there is still a object referencing this module object.

Suppose you have:

script a.js:

var b=require('./b.js').b;
exports.a='a from a.js';
exports.b=b;

and script b.js:

var a=require('./a.js').a;
exports.b='b from b.js';
exports.a=a;

when you do:

var a=require('./a.js')
var b=require('./b.js')

you will get:

> a
{ a: 'a from a.js', b: 'b from b.js' }
> b
{ b: 'b from b.js', a: undefined }

now if you edit your b.js:

var a=require('./a.js').a;
exports.b='b from b.js. changed value';
exports.a=a;

and do:

delete require.cache[require.resolve('./b.js')]
b=require('./b.js')

you will get:

> a
{ a: 'a from a.js', b: 'b from b.js' }
> b
{ b: 'b from b.js. changed value',
  a: 'a from a.js' }

===

The above is valid if directly running node.js. However, if using tools that have their own module caching system, such as jest, the correct statement would be:

jest.resetModules();
217
votes

If you always want to reload your module, you could add this function:

function requireUncached(module) {
    delete require.cache[require.resolve(module)];
    return require(module);
}

and then use requireUncached('./myModule') instead of require.

138
votes

Yes, you can access the cache via require.cache[moduleName] where moduleName is the name of the module you wish to access. Deleting an entry by calling delete require.cache[moduleName] will cause require to load the actual file.

This is how you would remove all cached files associated with the module:

/**
 * 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));
    }
};

Usage would be:

// Load the package
var mypackage = require('./mypackage');

// Purge the package from cache
purgeCache('./mypackage');

Since this code uses the same resolver require does, just specify whatever you would for require.


"Unix was not designed to stop its users from doing stupid things, as that would also stop them from doing clever things." – Doug Gwyn

I think that there should have been a way for performing an explicit uncached module loading.

41
votes

There's a Simple Module for that (with tests)

We had this exact issue while testing our code (delete cached modules so they can be re-required in a fresh state) so we reviewed all the suggestions of people on the various StackOverflow Questions & Answers and put together a simple node.js module (with tests):

https://www.npmjs.com/package/decache

As you would expect, works for both published npm packages and locally defined modules. Windows, Mac, Linux, etc.

Build Status codecov.io Code Climate maintainability Dependencies Status devDependencies Status

How? (usage)

Usage is pretty simple:

install

Install the module from npm:

npm install decache --save-dev

Use it in your code:

// require the decache module:
const decache = require('decache');

// require a module that you wrote"
let mymod = require('./mymodule.js');

// use your module the way you need to:
console.log(mymod.count()); // 0   (the initial state for our counter is zero)
console.log(mymod.incrementRunCount()); // 1

// delete the cached module:
decache('./mymodule.js');

//
mymod = require('./mymodule.js'); // fresh start
console.log(mymod.count()); // 0   (back to initial state ... zero)

If you have any questions or need more examples, please create a GitHub issue: https://github.com/dwyl/decache/issues

31
votes

For anyone coming across this who is using Jest, because Jest does its own module caching, there's a built-in function for this - just make sure jest.resetModules runs eg. after each of your tests:

afterEach( function() {
  jest.resetModules();
});

Found this after trying to use decache like another answer suggested. Thanks to Anthony Garvan.

Function documentation here.

16
votes

The solutions is to use:

delete require.cache[require.resolve(<path of your script>)]

Find here some basic explanations for those who, like me, are a bit new in this:

Suppose you have a dummy example.js file in the root of your directory:

exports.message = "hi";
exports.say = function () {
  console.log(message);
}

Then you require() like this:

$ node
> require('./example.js')
{ message: 'hi', say: [Function] }

If you then add a line like this to example.js:

exports.message = "hi";
exports.say = function () {
  console.log(message);
}

exports.farewell = "bye!";      // this line is added later on

And continue in the console, the module is not updated:

> require('./example.js')
{ message: 'hi', say: [Function] }

That's when you can use delete require.cache[require.resolve()] indicated in luff's answer:

> delete require.cache[require.resolve('./example.js')]
true
> require('./example.js')
{ message: 'hi', say: [Function], farewell: 'bye!' }

So the cache is cleaned and the require() captures the content of the file again, loading all the current values.

5
votes

rewire is great for this use case, you get a new instance with each call. Easy dependency injection for node.js unit testing.

rewire adds a special setter and getter to modules so you can modify their behaviour for better unit testing. You may

inject mocks for other modules or globals like process leak private variables override variables within the module. rewire does not load the file and eval the contents to emulate node's require mechanism. In fact it uses node's own require to load the module. Thus your module behaves exactly the same in your test environment as under regular circumstances (except your modifications).

Good news to all caffeine-addicts: rewire works also with Coffee-Script. Note that in this case CoffeeScript needs to be listed in your devDependencies.

4
votes

I'd add to luff's answer one more line and change the parameter name:

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)
}
4
votes

Yes, you can invalidate cache.

The cache is stored in an object called require.cache which you can access directly according to filenames (e.g. - /projects/app/home/index.js as opposed to ./home which you would use in a require('./home') statement).

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

Our team has found the following module useful. To invalidate certain groups of modules.

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

4
votes

I am not 100% certain of what you mean by 'invalidate', but you can add the following above the require statements to clear the cache:

Object.keys(require.cache).forEach(function(key) { delete require.cache[key] })

Taken from @Dancrumb's comment here

3
votes

I couldn't neatly add code in an answer's comment. But I would use @Ben Barkay's answer then add this to the require.uncache function.

    // 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 ];
        }
    }); 

Say you've required a module, then uninstalled it, then reinstalled the same module but used a different version that has a different main script in its package.json, the next require will fail because that main script does not exists because it's cached in Module._pathCache

3
votes

requireUncached with relative path: 🔥

const requireUncached = require => module => {
  delete require.cache[require.resolve(module)];
  return require(module);
};

module.exports = requireUncached;

invoke requireUncached with relative path:

const requireUncached = require('../helpers/require_uncached')(require);
const myModule = requireUncached('./myModule');
2
votes

If you want a module to simply never be cached (sometimes useful for development, but remember to remove it when done!) you can just put delete require.cache[module.id]; inside the module.

1
votes

Following two step procedure is working perfectly for me.

After changing Model file i-e 'mymodule.js' dynamically, you need to Delete precompiled model in mongoose model first then reload it using 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');
1
votes

The documentation says:

Modules are cached in this object when they are required. By deleting a key value from this object, the next require will reload the module. This does not apply to native addons, for which reloading will result in an error.

1
votes

here's my version of this answer, which handles not loading a file if it has (for example) syntax errors

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;
 }

}
0
votes

If it's for unit tests, another good tool to use is proxyquire. Everytime you proxyquire the module, it will invalidate the module cache and cache a new one. It also allows you to modify the modules required by the file that you are testing.

0
votes

I made a small module to delete module from the cache after loading. This forces reevaluation of the module next time it is required. See 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: you can also put "self-destruct" into the module itself. See https://github.com/bahmutov/unload-me

PSS: more tricks with Node require in my https://glebbahmutov.com/blog/hacking-node-require/