Node.js 为什么require()在从其他位置加载时会给我一个新的模块副本?

Node.js 为什么require()在从其他位置加载时会给我一个新的模块副本?,node.js,coffeescript,hubot,Node.js,Coffeescript,Hubot,我是Node.JS开发的新手,我正在尝试创建一个Hubot适配器 hubot模块导出一个名为TextMessage我需要使用的类。在我的适配器中,我创建了一个实例,并将其传递给正在运行的机器人,如下所示: {Adapter, TextMessage} = require 'hubot' class MyAdapter extends Adapter onNewMessage: (text) => @receive new TextMessage text 然而。当我运行bot

我是Node.JS开发的新手,我正在尝试创建一个Hubot适配器

hubot
模块导出一个名为
TextMessage
我需要使用的类。在我的适配器中,我创建了一个实例,并将其传递给正在运行的机器人,如下所示:

{Adapter, TextMessage} = require 'hubot'
class MyAdapter extends Adapter
  onNewMessage: (text) =>
    @receive new TextMessage text
然而。当我运行bot并使用适配器时,此检查总是失败

项目结构如下所示:

my-bot
 |- node_modules
    |- my-adapter
    |  |- node_modules
    |  |  |- hubot
    |- hubot  
因此,
my adapter
中的
require('hubot')
为我提供了一个与
my bot
不同的
hubot
模块副本


我很确定我没有理解节点模块的一些基本概念。我做错了什么?

之所以采用这种设计方式,是因为模块可以始终获得“新”版本(未被任何库(如您的库)修改)。通常,如果您
require()
一个依赖项,那么您应该能够依赖该模块的默认行为。(另一种选择是不可预测的,也可能是不安全的。)

如果您的模块的目的是调整另一个模块,那么您应该:

返回修改过的模块 例如,您的模块可能会执行以下操作:

module.exports = require('hubot');
// ... your custom modifications
或:

这意味着应用程序本身将不依赖于
hubot
,而只依赖于您的模块

不要将
hubot
列为适配器的依赖项 Node.js
require()
调用级联路径-因此,如果您只是不将
hubot
作为依赖项安装,那么您仍然可以
require()
它,它将使用应用程序中的版本

这意味着可以在不安装
hubot
的情况下安装您的模块,从而导致问题-但另一方面,它也允许多个模块修改相同的基本模块


就个人而言,我会选择第二个选项。

啊,我没有意识到
require()
调用会级联到目录路径。由于没有真正的理由在现有hubot实例的上下文之外使用我的模块,我将从我的模块中删除
hubot
作为依赖项。我强烈建议避免第二个选项。这将导致您的模块非常依赖于环境(如果
hubot
没有安装在它上面的某个位置,它将崩溃)。第一个选项是节点模块的预期设计方式。我已经看到第二个模式用于一些非常流行的模块,这些模块被设计成这样进行扩展。例如,模块将OAuth支持添加到
passport
,但它没有
passport
作为依赖项。这样,您就可以使用来自不同模块的一系列不同功能来增强Passport,这在第一个选项中是不可能的。
var hubot = module.exports.hubot = require('hubot');