【问题标题】:Accessing a node.js global module访问 node.js 全局模块
【发布时间】:2025-12-21 17:35:11
【问题描述】:

npm 文档是这样说的:

  • 如果您正在安装要在程序中使用的内容,请使用 require('whatever'),然后将其安装在本地,在项目的根目录下。
  • 如果您要在 shell 中安装要使用的东西,请在命令行或 一些东西,全局安装它,以便它的二进制文件最终出现在您的 PATH 环境变量中。

我目前正在编写 --- 或者至少正在尝试编写 --- 一个真正的 node 命令行程序,旨在从 shell 中使用。因此,根据上述情况,我的依赖项应该安装为全局模块。

我如何真正使用在 node 中使用 npm 安装的全局模块?当然,调用 require() 不起作用,因为默认情况下 npm 全局模块目录 (/usr/local/lib/node_modules) 不在路径上。我可以通过将其显式添加到程序顶部的路径来使其工作,但这是一个非常糟糕的解决方案,因为它不可移植——它需要知道 npm 的全局模块目录在任何给定系统上的位置。

只是为了让生活更加糟糕,我通过 dpkg 安装了一些全局模块。这些已经放在/usr/lib/nodejs 中,它们可以正常工作。这让我感到困惑,因为如果不应该将全局模块用于普通应用程序,我不希望它们都不会在路径上;否则我希望他们都在路上,并要求全局模块在任何地方都可以工作。有一个但没有另一个似乎很奇怪。这是怎么回事?

更新:我应该指出,这个程序只是一个脚本,顶部有#!/usr/bin/env nodejs;它不是一个正式的节点模块,这对于如此微不足道的事情来说太过分了。由于 Debian 模块在这样的脚本中都是必需的,对我来说 npm 的全局模块也应该是必需的似乎是明智的,但我感觉这是 Debian 主义......

【问题讨论】:

    标签: node.js


    【解决方案1】:

    因此,根据上述,我的依赖项应该安装为全局模块。

    不完全是。

    这意味着 您的模块 可以作为全局安装,因此它的 binaries 可以从 shell 获得:

    npm install -g your-module
    your-module-binary --option etc.
    

    另一方面,它的依赖项应该安装在第 1 点之后,驻留在项目中的 node_modules 目录中(通常在 package.json 中指定,因此 npm 可以管理它们)。

    但是,全局模块(通常)不适用于require。它们不遵循Loading from node_modules folders,而npm 遵循本地模块,并且它们的路径通常不在Loading from global foldersNODE_PATH 变量中列出。

    【讨论】:

      【解决方案2】:

      因此,您的说明与 npm 模块有关,但您正在进行本地开发。以下是一些准则。

      就你的源代码而言,你只需要2种require语句

      var dep = require('somedep')
      

      将此用于任何核心模块(如fs)和第三方模块,您的库需要您通过 npm 包含(在您的 package.json 中将它们列为依赖项)。在这里你指定一个不合格的包名,节点根据它的搜索算法找到模块。

      var mymod = require('./lib/mymod')
      

      使用它来通过相对于当前 javascript 文件的路径来要求项目本身中的其他模块。

      这就是您处理 javascript 依赖项所要做的所有事情。

      好的,现在如何安装依赖项?

      对于本地开发(在您的项目的源代码树中),只需 cd 进入项目目录并运行 npm install,它将读取您的 package.json 文件并在 node_modules 子目录中安装您需要的模块,所有将是非常适合本地发展。

      如果您将其实际发布为 npm 模块,其他用户(您既可以是开发人员,也可以是“其他用户”之一)如果他们想访问您项目的二进制文件,可以使用 npm -g 安装它PATH 上的实用程序需要包含 /usr/lib/nodejs/lib/node_modules,但在这种情况下,npm -g 将同时处理您的代码和项目的依赖项的安装。

      这就是你感到困惑的地方。

      因此,根据上述,我的依赖项应该安装为全局模块。

      您不需要将依赖项显式安装为全局变量,只需要您感兴趣的*模块,在这种情况下就是您的项目本身。 npm 将自动处理依赖关系,这是它在生活中的主要目的。您的项目的依赖项不会被全局安装,而是安装在项目的 node_modules 子目录中,它将被全局安装。

      这是目录和那里的内容:

      • ~/yourproject:为您的源代码进行本地开发
      • ~/yourproject/node_modules:你的项目在开发过程中使用的 npm 模块。通过在~/yourproject 中运行npm install 创建/填充
      • /usr/lib/nodejs/lib/node_modules:全局安装的 npm 模块(如果您将其发布到 npm 注册表,最终可能包括您的项目)
      • /usr/lib/nodejs/lib/node_modules/yourproject/node_modules:当您执行 npm install -g yourproject 时,您的项目的依赖项将安装在这里

      您可能还会发现my blog post on managing interpreters and the PATH 相关。

      【讨论】:

      • 是的,但这仅适用于重量级项目,而事实并非如此:这实际上是一个 shell 脚本,一个顶部带有 #!/usr/bin/env nodejs 的源文件。它将被困在/usr/local/bin 以供机器上的其他用户使用。强迫用户创建本地项目目录以便他们可以运行这是不合理的。鉴于脚本已经可以使用require() 访问 Debian 全局模块,为什么我不能访问 npm 的?
      • 你把用户和开发者混为一谈了。对于用户,您将模块发布到 npm 注册表,用户只需键入 npm install -g yourproject 即可完成。如果您在 package.json 中将 shell 脚本包装器标记为二进制文件(请参阅 npm help json),npm 会将其放在正确的位置,以便用户可以运行它。
      • 但是我没有模块,这就是我的意思。没有 package.json 也没有 shell 脚本包装器。我知道我不需要模块来执行此操作,因为如果我尝试访问 Debian 已安装的节点模块,一切都会正常工作。只是 npm 不起作用。我开始怀疑 npm 不支持这个用例,并且 Debian 已经摆弄了他们的节点设置以明确地使其工作。这看起来有道理吗?
      • 如果你有一个 node 程序并且你至少有 1 个非核心依赖,你应该创建一个 package.json 来跟踪你的依赖。你在技术上必须吗?不,但你应该这样做,因为它会避免混乱和问题。所以,弄清楚你的依赖是什么,并创建一个简单的 package.json 来跟踪它们。通过npm install 将它们安装在您的项目目录中。现在您可以创建一个包装脚本,该脚本将 cd 进入您的项目目录,然后像 cd /path/to/project && /usr/lib/nodejs/bin/node ./program.js 这样运行节点。
      【解决方案3】:

      此外,Node.js 将在以下 GLOBAL_FOLDERS 列表中搜索:

      1: $HOME/.node_modules 2:$HOME/.node_libraries 3: $PREFIX/lib/node

      【讨论】: