如何避免节点需要加载相同的模块两次

我正在开发一个节点模块my-module ,而这又取决于另一个模块other-moduleother-module是一个在我的模块的package.json中明确列出的依赖项。

因为我other-module只是通过require d来修改other-module模块的行为,所以重要的是other-module other-modulerequire加载一次,并且这个一次性的“实例”是在任何需要my应用程序中引用的实例和other

我期望这根据节点的模块caching策略保持真实,但是我在写一个简单的testing应用程序时遇到了这样的情况:

如果my-modulenpm install other-module 之前,那么后者是作为前者的依赖而引入的。 npm install other-module再次将其带入node_modules层次结构中。 然后,当我的模块需要other-module ,节点加载我的模块的“本地”副本,当应用程序require时,节点再次加载它(这次是由于第二次npm install而安装的版本)。 这显然不是预期的结果。

如果my-modulenpm installe other-module那么我最终只有一个在node_modules other-module的副本,我的testing应用程序按预期工作。

这种行为让我再次查看节点的相关策略,果然我遇到了“模块caching警告”:

模块基于他们parsing的文件名被caching。 由于模块可能会根据调用模块的位置(从node_modules文件夹加载)parsing为不同的文件名,因此不能保证require('foo')将始终返回完全相同的对象,如果parsing为不同的文件。

在这一点上,它看起来像我的模块可能会或可能不会像预期的取决于npm install的顺序。

我有什么最佳做法吗? 有没有办法避免这个混乱,而不改变我的模块的工作方式?

简短的回答:你不能。

正如你所指出的那样,节点将从最本地的地方加载所需的模块。 就我所知,这是一个独立于包pipe理器的东西,它使您不必关心模块的确切依赖关系树。 节点和NPM将为您解决这个问题。 在我看来,这是非常好的。

通过给你的模块提供一个需要的确切版本的机会,简单地避免依赖地狱。

我认为你所要做的,除非我完全不了解你的问题,不是好的节点实践。 模块被加载并分配给一个局部variables。 应避免全局状态,因为这可能会导致相当尴尬和不可测的代码。 另外,如果你能成功地修改过的模块注入到其他的人员代码中,那么不能保证他们的代码仍然可以工作。 这就像在老式的Prototype.js中一样,可以利用JavaScript内置的全局variables如String或者Array来破解代码。

但请记住,这个写作只是一个人的意见。 如果您在这里找不到更多答案,请在其他地方发布您的问题,如节点的IRC频道。

用开玩笑来开发testing时,我遇到了类似的问题。

以下语句将允许您在不同的上下文中再次加载相同的模块:

 jest.resetModules();