注意:这个答案解决了 OP 的特定用例:在给定项目的上下文中调用 依赖包的 CLI; 不是关于使 CLI全球可用 - 请参阅底部的讨论。
tl;博士:
在 Unix 类平台上,将npm run env -- 添加到您的命令中;例如:
npm run env -- mocha --recursive test/**/*.js --compilers js:babel-register
这不仅可以仅通过名称调用依赖 CLI,还可以在您使用 npm test 或 npm run-script <script-defined-in-package.json> 时完全复制 npm 在幕后设置的环境。
遗憾的是,这种方法不适用于 Windows。
对于 Windows 解决方案、便利别名(包括每会话一次的环境配置命令)和背景信息,请继续阅读。
有两种(不相互排斥的)方法可以使 npm 项目的依赖项的 CLI 可以通过 shell 的名称调用:
- (a) 使用 per-invocation 辅助命令,将命令传递给。
- (b) 运行 once-per-session 命令(临时)修改您的环境。
Frxstrem's helpful answer 为 (a) 在类 Unix 平台上提供了一个不完整的解决方案;但是,可能就足够了,具体取决于您的具体需求。
它是不完整的,因为它只是将包含依赖 CLI(符号链接)的目录添加到 $PATH,而不执行调用 npm test 或 npm run-script <script-defined-in-package.json 时发生的所有其他环境修改。
Unix 便利性和 Windows 解决方案
请注意,以下所有解决方案均基于 npm run env,这可确保设置所有必要的环境变量,就像在项目的 package.json 文件中使用 @ 预定义的运行脚本时一样987654333@ 或 npm run-script <script>.
这些环境修改包括:
- 将
$(npm prefix -g)/node_modules/npm/bin/node-gyp-bin 和项目目录的./node_modules/.bin 子目录(临时)添加到$PATH 环境变量,这是依赖项的CLI 的符号链接所在的位置。
- 定义多个反映项目设置的
npm_* 环境变量,例如npm_package_version 以及npm / node 环境。
类 Unix 平台的便捷解决方案:
以下两种解决方案均基于别名,在 (a) 的情况下,它是使用 脚本的更轻量级的替代方案>,在 (b) 的情况下,是允许修改当前 shell 环境的先决条件(尽管也可以使用 shell 函数)。
为方便起见,将这些别名添加到您的 shell 配置文件/初始化中
文件。
(a) 每次调用帮助器:
定义
alias nx='npm run-script env --'
允许您通过添加 nx 来临时调用您的命令;例如:
nx mocha --recursive test/**/*.js --compilers js:babel-register
(b) 每会话一次配置命令:
alias npmenv='npm run env -- $SHELL'
运行 npmenv 进入设置了 npm 环境的子 shell,允许在该子 shell 中直接(仅按名称)调用相关 CLI。
换句话说,按如下方式使用:
cd ~/some-npm-project
npmenv # after this, you can run dependent CLIs by name alone; e.g., `mocha ...`
# ... run your project-specific commands
exit # exit the child shell before you switch to a different project
Windows 解决方案:
(a) and (b):请注意,Windows(与类 Unix 平台上的类 POSIX shell 不同)不(直接)支持传递环境变量范围仅限于单个命令,因此下面的命令,即使通过特定命令执行(案例(a)),也总是修改会话的环境(案例(b))。
PowerShell(也适用于 Unix 版本):
将以下函数添加到您的$PROFILE(特定于用户的配置文件脚本):
function npmenv($commandIfAny) {
npm run env -- |
? { $_ -and $_ -notmatch '^>' -and $_ -match '^[a-z_][a-z0-9_]+=' } |
% { $name, $val = $_ -split '='; set-item -path "env:$name" -value $val }
if ($?) {
if ($commandIfAny) {
& $commandIfAny $Args
}
}
}
cmd.exe(常规命令提示符,常被误称为“DOS 提示符”):
创建一个名为npmenv.cmd的批处理文件,将其放在%PATH%的文件夹中,并定义如下:
@echo off
:: Set all environment variables that `npm run env` reports.
for /f "delims==; tokens=1,*" %%i in ('npm run env ^| findstr /v "^>"') do set "%%i=%%j"
:: Invoke a specified command, if any.
%*
用法(cmd.exe 和 PowerShell):
对于用例 (b),简单地调用 npmenv 不带参数;之后,您可以仅通过名称 (mocha ...) 调用依赖的 CLI。
对于用例 (a),在您的命令前添加 npmenv;例如:
npmenv mocha --recursive test/**/*.js --compilers js:babel-register
警告:如前所述,npmenv 的第一次 调用 - 无论是否有参数 - 都会在会话的剩余部分修改 %PATH% / $env:PATH 变量。
如果您在同一会话中切换到不同的项目,请务必再次运行 npmenv(至少一次),但请注意,这会将 附加 目录添加到 %PATH%,因此您如果它不是现在当前项目的已安装依赖项,您仍然可能最终意外运行以前项目的可执行文件。
在 PowerShell 中,您实际上可以结合这两种解决方案来获得不同的 (a) 和 (b) 功能:将上面的 *.cmd 文件定义为不同的命令(使用不同的名称例如nx.cmd),您只使用带参数 (a),并重新定义 PowerShell 函数以用作无参数环境仅修改补充 (b)。
这是可行的,因为 PowerShell 总是在不能影响当前 PowerShell 会话环境的 子 进程中运行 *.cmd 文件。
关于问题范围和此答案的说明:
OP 的问题是关于在给定项目的上下文中调用 已安装的依赖包的 CLI,仅通过可执行名称来临时调用 - 正如 npm 允许您在添加到package.json 文件中scripts 键的命令。
问题不是关于使 CLI全球可用(通过使用 npm install -g 安装它们)。
事实上,如果你想编写模块化、自包含的包,不要依赖于全局安装的包。相反,让所有依赖包成为你项目的一部分:使用npm install --save(用于运行时依赖)和npm install --save-dev(用于仅开发时间的依赖) - 请参阅https://docs.npmjs.com/cli/install
特别是,如果给定的 CLI 已作为 依赖项 安装,则全局安装它以及(可能是不同的版本)不仅是多余的,而且要求何时执行哪个版本的混淆。