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

bir*_*ril 6 javascript module require node.js npm

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

由于我的模块修改的行为other-module由被刚required,重要的是,other-module只加载一次,而这,一个和唯一的"实例"是一个贯穿既需要任何应用程序所引用myother.

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

如果my-modulenpm install other-module那么后者则带来了作为前者的依赖.npm install荷兰国际集团other-module之后带来入node_modules层次结构中的第二次.然后,当我的模块需要时other-module,节点加载我的模块的"本地"副本,当应用程序再次require加载它,(这次是由于第二次安装的版本npm install).这显然不是预期的结果.

如果my-modulenpm installed 之后, other-module我最终得到other-modulenode_modules的一个副本,我的测试应用程序按预期工作.

这种行为让我再次查看节点的相关策略,果然我遇到了"模块缓存注意事项":

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

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

我缺少哪些最佳实践?有没有办法避免这种混乱而不改变我的模块的工作方式?

top*_*pek 3

简短的回答:你不能。

正如您所指出的,节点将从最本地的位置加载所需的模块。据我所知,这是包管理器所独有的,它使您不必关心模块的确切依赖关系树。Node 和 npm 会为你解决这个问题。在我看来,这确实是一件好事。

通过让您的模块有机会要求其所需的精确版本,可以轻松避免依赖地狱。

我认为除非我完全理解你的问题,否则你想要做的事情并不是好的节点实践。模块被加载并分配给局部变量。应避免全局状态,因为这可能会导致相当尴尬且无法测试的代码。此外,如果您成功地将修改后的模块注入其他人的代码中,则无法保证他们的代码仍然有效。这就像在旧的Prototype.js时代一样,当时可以使用 JavaScript 的内置全局变量(如StringArray )进行修改,但这会导致一些灾难性的代码。

但请记住,本文仅代表一个人的观点。如果您在此处找不到更多答案,请将您的问题发布到其他地方,例如节点的 IRC 频道。