简体   繁体   English

如何在 node.js 中的“require”之后删除模块?

[英]How to remove module after “require” in node.js?

Let say, after I require a module and do something as below:假设,在我需要一个模块并执行以下操作之后:

var b = require('./b.js');
--- do something with b ---

Then I want to take away module b (ie clean up the cache).然后我想带走模块b(即清理缓存)。 how I can do it?我该怎么做?

The reason is that I want to dynamically load/ remove or update the module without restarting node server.原因是我想在不重新启动节点服务器的情况下动态加载/删除或更新模块。 any idea?任何的想法?

------- more -------- based on the suggestion to delete require.cache, it still doesn't work... -------更多--------基于建议删除require.cache,还是不行...

what I did are few things:
1) delete require.cache[require.resolve('./b.js')];
2) loop for every require.cache's children and remove any child who is b.js
3) delete b

However, when i call b, it is still there!但是,当我调用 b 时,它仍然存在! it is still accessible.它仍然可以访问。 unless I do that:除非我这样做:

b = {};

not sure if it is a good way to handle that.不确定这是否是处理它的好方法。 because if later, I require ('./b.js') again while b.js has been modified.因为如果稍后,我再次 require ('./b.js') 而 b.js 已被修改。 Will it require the old cached b.js (which I tried to delete), or the new one?它需要旧的缓存 b.js(我试图删除它)还是新的?

----------- More finding -------------- ----------- 更多发现--------------

ok.行。 i do more testing and playing around with the code.. here is what I found:我做了更多的测试和玩代码..这是我发现的:

1) delete require.cache[]  is essential.  Only if it is deleted, 
 then the next time I load a new b.js will take effect.
2) looping through require.cache[] and delete any entry in the 
 children with the full filename of b.js doesn't take any effect.  i.e.
u can delete or leave it.  However, I'm unsure if there is any side
effect.  I think it is a good idea to keep it clean and delete it if
there is no performance impact.
3) of course, assign b={} doesn't really necessary, but i think it is 
 useful to also keep it clean.

You can use this to delete its entry in the cache:您可以使用它来删除它在缓存中的条目:

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

require.resolve() will figure out the full path of ./b.js , which is used as a cache key. require.resolve()将计算出的全路径./b.js ,其被用作缓存键。

One of the easiest ways (although not the best in terms of performance as even unrelated module's caches get cleared) would be to simply purge every module in the cache最简单的方法之一(尽管在性能方面不是最好的,因为即使不相关的模块的缓存也被清除了)是简单地清除缓存中的每个模块

Note that clearing the cache for *.node files (native modules) might cause undefined behaviour and therefore is not supported ( https://github.com/nodejs/node/commit/5c14d695d2c1f924cf06af6ae896027569993a5c ), so there needs to be an if statement to ensure those don't get removed from the cache, too.请注意,清除*.node文件(本机模块)的缓存可能会导致未定义的行为,因此不受支持( https://github.com/nodejs/node/commit/5c14d695d2c1f924cf06af6ae896027569993a5c ),因此需要一个 if 语句确保这些也不会从缓存中删除。

    for (const path in require.cache) {
      if (path.endsWith('.js')) { // only clear *.js, not *.node
        delete require.cache[path]
      }
    }

Spent some time trying to clear cache in Jest tests for Vuex store with no luck.花了一些时间尝试清除 Vuex 商店的 Jest 测试中的缓存,但没有成功。 Seems like Jest has its own mechanism that doesn't need manual call to delete require.cache.似乎 Jest 有自己的机制,不需要手动调用删除 require.cache。

beforeEach(() => {
  jest.resetModules();
});

And tests:和测试:

let store;

it("1", () => {
   process.env.something = true;
   store = require("@/src/store.index");
});

it("2", () => {
   process.env.something = false;
   store = require("@/src/store.index");
});

Both stores will be different modules.两个商店将是不同的模块。

I have found the easiest way to handle invalidating the cache is actually to reset the exposed cache object.我发现处理无效缓存的最简单方法实际上是重置公开的缓存对象。 When deleting individual entries from the cache, the child dependencies become a bit troublesome to iterate through.当从缓存中删除单个条目时,子依赖项变得有点难以迭代。

 require.cache = {};

I found this useful for client side applications.我发现这对客户端应用程序很有用。 I wanted to import code as I needed it and then garbage collect it when I was done.我想在需要时导入代码,然后在完成后进行垃圾回收。 This seems to work.这似乎有效。 I'm not sure about the cache, but it should get garbage collected once there is no more reference to module and CONTAINER.sayHello has been deleted.我不确定缓存,但是一旦没有更多对module引用并且CONTAINER.sayHello已被删除,它应该会被垃圾收集。

/* my-module.js */

function sayHello { console.log("hello"); }

export { sayHello };

/* somewhere-else.js */

const CONTAINER = {};

import("my-module.js").then(module => {

  CONTAINER.sayHello = module.sayHello;

  CONTAINER.sayHello(); // hello

  delete CONTAINER.sayHello;

  console.log(CONTAINER.sayHello); // undefined

});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM