如何加载节点模块,就好像当前模块位于其他地方一样?
How do I load a node module as if the current module were located somewhere else?
我在某个模块中有一些 nodejs 代码 运行。从这个模块,我想加载一个位于文件系统中完全不同位置的模块——例如,给定路径 "/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
换句话说,module documentation指的是进程"require(X) from module at path Y",我想为Y
指定我自己的值
这能实现吗?如果是这样,如何?如果不是,为什么不呢?
最简单的,就是将路径解析为绝对路径,即使不是所有情况,这也是大多数情况下的推荐方法。
var path = require('path');
var basedir = '/another/dir';
var filename = 'foo'; // renamed from dirname
var filepath = path.join(basedir, 'node_modules', filename);
var imports = require(filepath);
如果您确实需要让 require 像在不同的目录中一样工作,
您可以将基本目录推送到 module.paths
module.paths.unshift('/another/dir/node_modules');
var imports = require('foo');
module.paths.shift();
module.paths
也可以通过环境变量 NODE_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');
对于演示,在终端中打开节点,然后键入 module.paths
,它将显示节点将搜索 require
的所有路径,您只需添加您的路径
"require(X) from module at path Y"
意味着从位于路径 Y 的文件中调用 require(X)。因此您实际上无法更改 Y。
尽管上述解决方案有效(修改 module.paths 并需要绝对路径),但您必须将这些片段添加到项目中需要外部模块的每个文件中。
更何况,官方不支持修改module.paths。所以它不能保证在节点的未来更新中工作
介绍 NODE_PATH
NODE_PATH 是一个环境变量,设置为以冒号分隔的绝对路径列表。
在这些绝对路径中,Node.js 将在所有其他方法都失败时搜索与您的 require 语句匹配的模块(索引 node_modules 最多文件系统根目录但仍未找到匹配项)
官方支持,但不推荐,因为它违反惯例(您的同事可能不知道 NODE_PATH 用法,因为没有描述性说明在您的项目本身中说明这一点的方式)
备注:
- 在 Windows 上,NODE_PATH 由分号分隔,而不是
冒号。
- Node 不会在这些路径中寻找 node_modules
它的默认行为,所以你的路径应该正是你
包含需要的模块。例如:“/another/dir/node_modules”
详细信息可以参考NodeJs官方文档:
https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
对于那些不知道什么是环境变量以及如何设置它们的人,我有一个 windows 屏幕截图可以帮助您入门
一个 symlink 与 npm link
为了避免问题或修改源代码,我会使用 npm link,从你的示例中:
第一个:
cd /another/dir/node_modules/foo # go into the package directory
npm link # creates global link
这将为 foo
模块创建全局 link,在 Linux 上,您需要 root 权限才能执行此操作。
然后:
cd /some/folder/ # go into some other package directory.
npm link foo # link-install the package
/some/folder/package.json
应该包含 foo
作为 dep,不是强制性的,没有它你会收到 npm ls
:
的 extraneous
警告
"dependencies": {
[...]
"foo": "*"
}
与本地NODE_PATH
无符号link
你不喜欢 symlinks 吗?您仍然可以使用 NODE_PATH
但在本地而不是按照@rocketspacer 的建议设置全局变量,因为正如他正确指出的那样,不建议在全局使用它。
注意:无论如何我会使用用户变量和不 系统范围的变量,一个同事可以在同一台机器上使用不同的用户名登录,并且仍然得到修改后的 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%
还有...
您也可以使用本地代理,例如:
"dependencies": {
"foo": "file:/another/dir/node_modules/foo"
}
但需要一个 npm install
并且它会在当前包 node_modules
文件夹中复制 foo
的内容。
简而言之,您可以将自己的文件夹称为模块:
为此我们需要:global 和 app-module-path 模块
此处 "App-module-path" 是模块,它使您可以将其他目录添加到 Node.js 模块搜索路径 "global" 是,您附加到此对象的任何内容都将可用在您的应用中无处不在。
现在看看这个片段:
global.appBasePath = __dirname;
require('app-module-path').addPath(appBasePath);
__dirname是node.You的当前运行目录可以在这里给自己的路径搜索模块的路径。
我在某个模块中有一些 nodejs 代码 运行。从这个模块,我想加载一个位于文件系统中完全不同位置的模块——例如,给定路径 "/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
换句话说,module documentation指的是进程"require(X) from module at path Y",我想为Y
指定我自己的值
这能实现吗?如果是这样,如何?如果不是,为什么不呢?
最简单的,就是将路径解析为绝对路径,即使不是所有情况,这也是大多数情况下的推荐方法。
var path = require('path');
var basedir = '/another/dir';
var filename = 'foo'; // renamed from dirname
var filepath = path.join(basedir, 'node_modules', filename);
var imports = require(filepath);
如果您确实需要让 require 像在不同的目录中一样工作,
您可以将基本目录推送到 module.paths
module.paths.unshift('/another/dir/node_modules');
var imports = require('foo');
module.paths.shift();
module.paths
也可以通过环境变量 NODE_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');
对于演示,在终端中打开节点,然后键入 module.paths
,它将显示节点将搜索 require
的所有路径,您只需添加您的路径
"require(X) from module at path Y"
意味着从位于路径 Y 的文件中调用 require(X)。因此您实际上无法更改 Y。
尽管上述解决方案有效(修改 module.paths 并需要绝对路径),但您必须将这些片段添加到项目中需要外部模块的每个文件中。
更何况,官方不支持修改module.paths。所以它不能保证在节点的未来更新中工作
介绍 NODE_PATH
NODE_PATH 是一个环境变量,设置为以冒号分隔的绝对路径列表。
在这些绝对路径中,Node.js 将在所有其他方法都失败时搜索与您的 require 语句匹配的模块(索引 node_modules 最多文件系统根目录但仍未找到匹配项)
官方支持,但不推荐,因为它违反惯例(您的同事可能不知道 NODE_PATH 用法,因为没有描述性说明在您的项目本身中说明这一点的方式)
备注:
- 在 Windows 上,NODE_PATH 由分号分隔,而不是 冒号。
- Node 不会在这些路径中寻找 node_modules 它的默认行为,所以你的路径应该正是你 包含需要的模块。例如:“/another/dir/node_modules”
详细信息可以参考NodeJs官方文档:
https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
对于那些不知道什么是环境变量以及如何设置它们的人,我有一个 windows 屏幕截图可以帮助您入门
一个 symlink 与 npm link
为了避免问题或修改源代码,我会使用 npm link,从你的示例中:
第一个:
cd /another/dir/node_modules/foo # go into the package directory
npm link # creates global link
这将为 foo
模块创建全局 link,在 Linux 上,您需要 root 权限才能执行此操作。
然后:
cd /some/folder/ # go into some other package directory.
npm link foo # link-install the package
/some/folder/package.json
应该包含 foo
作为 dep,不是强制性的,没有它你会收到 npm ls
:
extraneous
警告
"dependencies": {
[...]
"foo": "*"
}
与本地NODE_PATH
无符号link你不喜欢 symlinks 吗?您仍然可以使用 NODE_PATH
但在本地而不是按照@rocketspacer 的建议设置全局变量,因为正如他正确指出的那样,不建议在全局使用它。
注意:无论如何我会使用用户变量和不 系统范围的变量,一个同事可以在同一台机器上使用不同的用户名登录,并且仍然得到修改后的 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%
还有...
您也可以使用本地代理,例如:
"dependencies": {
"foo": "file:/another/dir/node_modules/foo"
}
但需要一个 npm install
并且它会在当前包 node_modules
文件夹中复制 foo
的内容。
简而言之,您可以将自己的文件夹称为模块:
为此我们需要:global 和 app-module-path 模块
此处 "App-module-path" 是模块,它使您可以将其他目录添加到 Node.js 模块搜索路径 "global" 是,您附加到此对象的任何内容都将可用在您的应用中无处不在。
现在看看这个片段:
global.appBasePath = __dirname;
require('app-module-path').addPath(appBasePath);
__dirname是node.You的当前运行目录可以在这里给自己的路径搜索模块的路径。