访问node.js全局模块

8
npm文档中说道:
  • 如果你要安装的东西是用来在程序中使用的,比如 require('whatever'),那么请在项目的根目录下本地安装
  • 如果你要安装的东西是用来在shell命令行中使用的,则需要全局安装,这样它的二进制文件就会被加入到PATH环境变量中去
我正在编写一个用于shell的node命令行程序,因此根据上面所说,我的依赖应该作为全局模块进行安装。但是,我该如何在node中实际使用通过npm安装的全局模块呢?当然不能通过调用require()来解决,因为默认情况下,npm的全局模块目录(/usr/local/lib/node_modules)没有添加到路径中。我可以通过在程序顶部显式添加路径来使其工作,但这不是一个好的解决方案,因为它并不可移植 - 它需要知道在任何给定系统中npm的全局模块目录在哪里。更让人恼火的是,我有一些通过dpkg安装的全局模块。它们被放在了 /usr/lib/nodejs 中,而且它们正常工作。这让我感到困惑,因为如果全局模块不适用于普通应用程序,我希望两者都不在路径上;否则,我希望它们都在路径上,并且全局模块应该能够在任何地方正常工作。现在只有一种情况似乎很奇怪,这是怎么回事?更新:我应该指出这个程序只是一个脚本,在顶部有#!/usr/bin/env nodejs,它不是一个正式的node模块,因为对于这种微不足道的东西来说使用node模块就过度了。由于Debian模块都可以从这样的脚本中调用,所以对我来说,npm的全局模块也可以被调用,但我感觉这是一个Debianism...
3个回答

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

并非完全如此。

这意味着您的模块可以作为全局安装,以便其二进制文件可以从shell中使用:

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

而另一方面,它的依赖应该在第1点后安装,在您的项目中的node_modules目录中(通常在package.json中指定,以便npm进行管理)。

但是,全局模块不会(通常)对require可用。 它们不遵循node_modules文件夹加载,这是npm用于本地模块的方式,并且它们的路径通常不列在NODE_PATH变量中以进行从全局文件夹加载


1

所以你现在的指令是关于npm模块的,但你正在进行本地开发。以下是一些指南。

就你的源代码而言,你只需要两种类型的require语句。

var dep = require('somedep')

对于任何核心模块(如fs)和您的库需要通过npm包含的第三方模块(在package.json中列出它们作为依赖项),请使用此选项。在这里,您指定一个未经限定的软件包名称,Node会根据其搜索算法找到该模块。

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

使用此方法,通过相对于当前JavaScript文件的路径在项目中引用其他模块。

这就是处理JavaScript依赖项所需做的全部操作。

好了,现在该如何安装您的依���项呢?

对于本地开发(在项目源树内),只需进入项目目录并运行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 时,您的项目的依赖项将在此处安装

您可能也会发现我关于管理解释器和PATH的博客文章相关。


是的,但这只适用于重量级项目,而这并不是:实际上,这是一个 shell 脚本,一个带有 #!/usr/bin/env nodejs 的源文件。它将被固定在 /usr/local/bin 中,以供机器上的其他用户使用。强迫用户创建一个本地项目目录,只是为了运行这个脚本是不合理的。考虑到该脚本已经可以使用 require() 访问 Debian 全局模块,为什么我不能访问 npm 的模块呢? - David Given
你正在混淆用户和开发人员。对于用户,你需要将你的模块发布到npm注册表中,用户只需输入 npm install -g yourproject 即可完成安装。如果你在 package.json 中将你的 shell 脚本包装器标记为二进制文件(参见 npm help json),npm 将把它放在正确的位置,以便用户可以运行它。 - Peter Lyons
但是我没有模块,这就是我的问题。没有 package.json 和 shell 脚本包装器。我知道我不需要一个模块来做这件事,因为如果我尝试访问 Debian 安装的 node 模块,一切都可以正常工作。只有 npm 不起作用。我开始怀疑 npm 不支持这种用例,并且 Debian 已经修改了他们的 node 设置以显式使其工作。这听起来可信吗? - David Given
如果你有一个Node程序,并且至少有1个非核心依赖项,那么你应该创建一个package.json来跟踪你的依赖项。从技术上讲,你需要吗?不是的。但是你应该这样做,因为这将避免混乱和问题。所以,确定你的依赖关系,并创建一个简单的package.json来跟踪它们。通过npm install在项目目录内安装它们。现在您可以创建一个包装器脚本,它将cd到您的项目目录,然后运行node,如cd /path/to/project && /usr/lib/nodejs/bin/node ./program.js - Peter Lyons

0
此外,Node.js 还会在以下全局文件夹列表中搜索:
1:$HOME/.node_modules 2:$HOME/.node_libraries 3:$PREFIX/lib/node

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接