Play it Again, Sam: Reloading Node.js modules
Play it Again, Sam: Reloading Node.js modules
Reloading modules in Node.js can be a bit tricky. After initially importing a module, subsequent calls to require
have no effect. Looking for something along the lines of Python’s reload
command I’ve arrived at this solution that allows modules to be reloaded (as well as imported the first time) with the following require.reload
command.
// Import a module
var mymodule = require('./mymodule')
// After making some changes to the module, reload it
mymodule = require.reload('./mymodule')
Reloading is accomplished by searching the cache for a specific module using require.searchCache
and removing that module and its children with require.uncache
. The real heavy lifting is done by the call to delete require.cache[mod.id]
. Below is the script for starting a modified repl that includes the additional require commands by default.
var myrepl = require("repl").start({});
/**
* Removes a module from the cache.
*/
myrepl.context.require.uncache = function (moduleName) {
// Run over the cache looking for the files
// loaded by the specified module name
myrepl.context.require.searchCache(moduleName, function (mod) {
delete require.cache[mod.id];
});
};
/**
* Runs over the cache to search for all the cached files.
*/
myrepl.context.require.searchCache = function (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 run(mod) {
// Go over each of the module's children and
// run over it
mod.children.forEach(function (child) {
run(child);
});
// Call the specified callback providing the
// found module
callback(mod);
})(mod);
}
};
/*
* Load a module, clearing it from the cache if necessary.
*/
myrepl.context.require.reload = function(moduleName) {
myrepl.context.require.uncache(moduleName);
return myrepl.context.require(moduleName);
};
It is worth noting that modules which start timers or initialize lazy objects might not be completely removed with the require.reload
command. However, for quick hacks in non-production environments this code is a real time saver. For the full script with some additional hints check out the github gist.