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

时间:2012-12-17 00:33:17

标签: javascript node.js module require npm

我正在开发一个节点模块my-module,后者依赖于另一个模块other-module。因此,other-module是我的模块的package.json中明确列出的依赖项。

由于我的模块只是other-module d修改了require的行为,因此other-module只加载一次并且这个唯一的'实例'非常重要是在任何需要myother的应用程序中引用的那个。

我希望根据节点的模块缓存策略保持这一点,但我在编写一个简单的测试应用程序时遇到的是:

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

如果my-module在<{em> npm installe之后为other-module d ,那么我最终只能使用 other-module的一个副本在node_modules中,我的测试应用程序按预期工作。

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

  

模块根据其解析的文件名进行缓存。由于模块可能会根据调用模块的位置(从node_modules文件夹加载)解析为不同的文件名,因此不能保证require('foo')将始终返回完全相同的对象,如果它将解析为不同的文件

此时看起来我的模块可能会或可能不会按预期运行,具体取决于npm install的顺序。

我缺少哪些最佳做法?有没有办法在不改变模块工作方式的情况下避免这种混乱?

2 个答案:

答案 0 :(得分:3)

简短回答:你不能。

正如您所指出的,node将从最本地的位置加载所需的模块。据我所知,这是包管理器的独特之处,它使您无需关心模块的确切依赖关系树。 Node和npm会为你解决这个问题。在我看来,这是非常好的。

通过让您的模块有机会需要他们所需的精确版本,可以避免依赖性地狱。

我认为你要做的事情,除非我不完全理解你的问题,不是好的节点练习。加载模块并将其分配给局部变量。应避免使用全局状态,因为这会导致相当笨拙和不可测试的代码。此外,如果您成功注入您修改过的模块转换为其他人的代码,则无法保证其代码仍可正常工作。这可以像旧的 Prototype.js _那样,可以使用JavaScript的内置全局变量(如 String Array)进行破解,这导致了一些灾难性的代码。

但请记住,这篇文章只是一个人的意见。如果您在此处找不到更多答案,请在节点的IRC频道之外的其他地方发布您的问题。

答案 1 :(得分:0)

我在用jest开发测试时遇到了类似的问题。

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

jest.resetModules();