如何加载节点模块,就好像当前模块位于其他地方一样?

我有一些nodejs代码在模块中运行。 从这个模块中,我想加载一个位于文件系统中完全不同位置的模块 – 例如,给定path"/another/dir"和模块名称"foo" ,我希望Node充当如果一个运行在/another/dir的模块调用了require("foo") ,而不是我自己的模块。

  My code is running here /some/folder/node_modules/mine/my_module.js I have the path "/another/dir/", the string "foo", and want to load this module /another/dir/node_modules/foo/index.js 

换句话说, 模块文档引用的过程是“从pathY的模块需要(X)” ,我想为Y指定自己的值

这能做到吗? 如果是这样,怎么样? 如果没有,为什么不呢?

最简单的方法就是将pathparsing为绝对path,对于大多数情况(如果不是全部情况),这将是推荐的方法。

 var path = require('path'); var basedir = '/another/dir'; var dirname = 'foo'; var filepath = path.join(basedir, 'node_modules', filename); var imports = require(filepath); 

如果您确实需要使其处于不同目录中,则可以将基本目录推送到module.paths

 module.paths.unshift('/another/dir/node_modules'); var imports = require('foo'); module.paths.shift(); 

module.paths也可以通过环境variablesNODE_PATH进行外部修改,这将是最不推荐的方法, 但这确实适用于所有模块的全局。

与npm链接的符号链接

为了避免问题或修改源代码,我将使用npm链接 ,在你的例子中:

第一:

 cd /another/dir/node_modules/foo # go into the package directory npm link # creates global link 

这将为foo模块创build一个全局链接,在Linux上你需要root权限来做到这一点。

然后:

 cd /some/folder/ # go into some other package directory. npm link foo # link-install the package 

/some/folder/package.json应该包含foo作为dep,不是必须的,没有它你会得到一个extraneous警告npm ls

 "dependencies": { [...] "foo": "*" } 

没有与本地NODE_PATH的符号链接

你不喜欢符号链接? 你仍然可以使用NODE_PATH但在本地,而不是设置一个全局variables作为@ rocketspacerbuild议,因为正如他所说,不build议全球使用它。

注意 :在任何情况下,我将使用Uservariables不是 System-widevariables ,同事可以在同一台计算机上使用不同的用户名login,并仍然获得修改的NODE_PATH

但是要在Linux上进行一次调用,您只需调用:

 NODE_PATH=$NODE_PATH:/another/dir/node_modules npm start 

只会为那个调用使用NODE_PATH

在Windows上同一次调用:

 @ECHO OFF SET BASE_NODE_PATH=%NODE_PATH% SET NODE_PATH=%BASE_NODE_PATH%;C:\another\dir\node_modules\ node index.js SET NODE_PATH=%BASE_NODE_PATH% 

和…

你也可以使用一个本地dep如:

 "dependencies": { "foo": "file:/another/dir/node_modules/foo" } 

但是需要一个npm install ,它会复制当前包的node_modules文件夹中的foo的内容。

这是很容易实现的,只需添加模块对象的绝对path

在你当前的脚本中/some/folder/node_modules/mine/my_module.js添加这个

 module.paths.push('/another/dir/node_modules'); //this must be absolute, like /Users/John/another/dir/node_modules var foo = require('foo'); 

对于演示,在terminal打开节点,并inputmodule.paths ,它会显示所有的path节点将searchrequire ,您只需添加您的path

“要求(X)从模块的pathY”

手段调用要求(X)从位于pathY的文件中。所以,你实际上不能改变Y.


虽然上面的解决scheme可以工作(修改module.paths和需要绝对path),但是您必须将这些代码片段添加到需要外部模块的项目中的每个文件中。

更重要的是,修改module.paths没有官方的支持。 所以不能保证在未来的节点更新中工作


介绍NODE_PATH

NODE_PATH是一个环境variables,设置为以冒号分隔的绝对path列表。

在这些绝对path中,Node.js将search与其他所有内容都失败时匹配您的require语句的模块(将node_modules索引到文件系统根目录 ,但仍未find匹配项)

这是正式支持,虽然不推荐,因为它违背惯例(你的同事可能不知道NODE_PATH的使用,因为没有描述性的方式告诉你的项目本身)

笔记:

  • 在Windows上, NODE_PATH由分号而不是冒号分隔。
  • 节点不会在这些path中寻找node_modules,就像它的默认行为一样,所以你的path应该正好在你包含需要的模块的地方。 例如:“/ another / dir / node_modules”

详细信息可以在NodeJs官方文档中find:
https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders


对于那些不了解什么是环境variables以及如何设置它们的人,我有一个可以让你开始的窗口截图

在这里输入图像描述

简单的说,你可以调用你自己的文件夹作为模块:

为此我们需要:global和app-module-path模块

在这里“App-module-path”是模块,它使您能够将额外的目录添加到Node.js模块searchpath而“全局”是,任何附加到这个对象的任何东西都可以在您的应用程序的任何地方使用。

现在看看这个片段:

 global.appBasePath = __dirname; require('app-module-path').addPath(appBasePath); 

__dirname是节点的当前运行目录。您可以在此处给自己的pathsearch模块的path。