Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decache removing all child dependencies of target module from cache #29

Open
andrsnn opened this issue Apr 4, 2017 · 5 comments
Open
Labels
documentation Improvements or additions to documentation help wanted If you can help make progress with this issue, please comment! question A question needs to be answered before progress can be made on this issue T25m Time Estimate 25 Minutes

Comments

@andrsnn
Copy link

andrsnn commented Apr 4, 2017

Currently when a module with child dependencies is removed from the require cache via decache, all of its child dependencies are also removed from the cache.

For example:

When requiring a module that requires several other modules.

a.js
    -- b.js
    -- c.js
        -- d.js

The require.cache will then contain references to each module.
e.g. Object.keys(require.cache) will look like:

[ '/Users/my-user/Documents/git/decache/my-test-file.js',
  '/Users/my-user/Documents/git/decache/decache.js',
  '/Users/my-user/Documents/git/decache/node_modules/callsite/index.js',
  '/Users/my-user/Documents/git/decache/a.js',
  '/Users/my-user/Documents/git/decache/b.js',
  '/Users/my-user/Documents/git/decache/c.js',
  '/Users/my-user/Documents/git/decache/d.js',
  '/Users/my-user/Documents/git/decache/e.js' ]

after calling decache on the a.js module

decache('./a')

The require cache will no longer contain references to the a.js module specified or any of its dependencies

e.g. Object.keys(require.cache) will look like:

[ '/Users/my-user/Documents/git/decache/my-test-file.js',
  '/Users/my-user/Documents/git/decache/decache.js',
  '/Users/my-user/Documents/git/decache/node_modules/callsite/index.js' ]

This is due to the fact that the decache module recursively DFS the target modules dependency tree. Deleting each module passed by the callback iterator.

// Run over the cache looking for the files
// loaded by the specified module name
require.searchCache(moduleName, function (mod) {
    delete require.cache[mod.id];
});

....

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 no else so #ignore else http://git.io/vtgMI
    /* istanbul ignore else  */
    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);
    }
};

Is this behavior intended? Should the DFS instead be removing all references to child.parent? I would assume that some people using this module are depending on this behavior or have worked around it. Curious as to thoughts on this.

Thanks!

@nelsonic nelsonic added the question A question needs to be answered before progress can be made on this issue label Apr 4, 2017
@nelsonic
Copy link
Member

@andrsnn this was our desired behaviour as we want the "child" dependencies to be "fresh".
if you would prefer that they were not removed, we could consider adding that as an optional parameter...

@albertogasparin
Copy link

@andrsnn If you don't need it to be recursive, then you just need to manually delete the key on the require.cache object:

delete require.cache['/Users/my-user/Documents/git/decache/a.js'];

That should be enough.

@boaz-amit
Copy link

boaz-amit commented Feb 7, 2018

@albertogasparin @andrsnn Note you're better off resolving the path:

delete require.cache[require.resolve('/Users/my-user/Documents/git/decache/a.js')];

Source: https://stackoverflow.com/questions/9210542/node-js-require-cache-possible-to-invalidate

@dwelle
Copy link

dwelle commented Nov 1, 2018

delete require.cache[require.resolve('/Users/my-user/Documents/git/decache/a.js')];

I assume we also need to run:

Object.keys(module.constructor._pathCache).forEach(function(cacheKey) {
    if (cacheKey.indexOf(moduleName)>0) {
        delete module.constructor._pathCache[cacheKey];
    }
});

From decache.js#L38... or not? What's that for, anyway?

@meelash
Copy link

meelash commented Sep 28, 2022

Could we add to the documentation the explicit info that it does this? This is in face the desired behavior, but I had to dig in the issues to figure it out, or else look in the source or download and try. Would be much preferred if you pointed out in the readme that this is what it does.

@nelsonic nelsonic added help wanted If you can help make progress with this issue, please comment! T25m Time Estimate 25 Minutes documentation Improvements or additions to documentation labels Sep 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation help wanted If you can help make progress with this issue, please comment! question A question needs to be answered before progress can be made on this issue T25m Time Estimate 25 Minutes
Projects
None yet
Development

No branches or pull requests

6 participants