7

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

由于我的模块other-module仅通过成为required 来修改 的行为,因此other-module仅加载一次并且这个唯一的“实例”是在需要my和的任何应用程序中引用的唯一的“实例”是很重要的other

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

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

如果my-modulenpm installed other-module那么我最终只得到一个other-modulein node_modules副本,并且我的测试应用程序按预期工作。

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

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

在这一点上,我的模块看起来可能会也可能不会像预期的那样运行,具体取决于npm installs 的顺序。

有没有我遗漏的最佳实践?有什么办法可以在不改变我的模块工作方式的情况下避免这种混乱?

4

2 回答 2

3

简短的回答:你不能。

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

通过让您的模块有机会要求他们需要的确切版本,可以简单地避免依赖地狱。

我认为除非我不完全理解您的问题,否则您正在尝试做的不是良好的节点实践。模块被加载并分配给一个局部变量。应该避免使用全局状态,因为这会导致相当笨拙和不可测试的代码。此外,如果您成功地将修改后的模块注入到其他人的代码中,则无法保证他们的代码仍然可以工作。这就像在旧的Prototype.js _ 日子里,可以使用 JavaScript 的内置全局变量(如StringArray )来破解,这会导致一些灾难性的代码。

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

于 2012-12-18T21:10:03.667 回答
0

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

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

jest.resetModules();
于 2017-01-13T02:28:25.290 回答