unloading code/modules

node.js

node.js Problem Overview


I'm curious if there is any good way to unload a module after using it. I have some cases where I need to use modules that bring in a lot of code, but they are used rarely (say as an admin tool), but I hesitate to use them because afterwards they'll presumably just waste memory that could be better used elsewhere. Is there any way to unload them, either explicitly or by allowing the system to do so when they haven't been used for a while?

node.js Solutions


Solution 1 - node.js

Yes, it is possible to access the module cache directly:

var name = require.resolve('moduleName');
delete require.cache[name];

Note that if your code carries a reference to whatever was exposed by these modules you want to get rid of, it won't be cleaned up.

(As an aside: Underneath the surface, require.resolve and require.cache are just proxies to Module._resolveFilename and Module._cache respectively, with Module being the core module loader, i.e. require('module').)

Solution 2 - node.js

You can do something like this to "unload" a node module:

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

"Unloading" a node module means that you're "deleting" its entry from node require cache. The snippet above transitively deletes one node module from the cache and all the associated modules (children modules).

In my case I was requiring "index.js" that, at the same time, was requiring "/lib/.js". I wanted to test initialization of "index.js" (and therefore the only other module being required in there which was /lib/.js). Deleting "index.js" from the cache was not enough because the cache maintained a separate reference to "/lib/.js" and that caused the module "/lib/.js" to not be loaded again from its file.

The code above might certainly delete from the cache other modules this module depends on (this is actually what I wanted BUT you might not want to do this for other modules like "fs", "path" or even "underscore").

You can always extend this method to accept a list of modules you don't want to delete or a filter you could apply to the "path" of the resolved module. You can say: don't delete core node modules (a list of core node modules names is available as a npm package: https://www.npmjs.com/package/node-core-module-names) or don't delete any of the packages under node_modules, etc etc.. This could be a filter inside the function but it's the same logic.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrobView Question on Stackoverflow
Solution 1 - node.jschjjView Answer on Stackoverflow
Solution 2 - node.jscSnView Answer on Stackoverflow