在" context"中运行节点命令在已安装的node_modules
中,您可以在scripts
的{{1}}字段中输入内容。例如:
package.json
然后我可以在项目根目录中键入...
"scripts": {
"test": "mocha --recursive test/**/*.js --compilers js:babel-register"
}
...
,然后运行mocha测试(通过调用npm run test
中安装的mocha二进制文件)。
有没有办法实现完全相同的行为,但没有创建脚本条目?例如,对于一次性"脚本"?
我想象以下内容,相当于node_modules/mocha/bin
:
npm run test
有没有办法实现这个目标?
注意:我应该澄清一点,我正在寻找真正的等价。也就是说,我的命令应该能够访问其他脚本命令等。我知道你总是可以使用node和node_modules中二进制文件的路径来调用二进制文件,但这不是一个合适的解决方案。
答案 0 :(得分:8)
注意:这个答案解决了OP的特定用例:在给定项目的上下文中调用依赖包的CLI ;关于使CLI 全球可用 < - > - 参见讨论的底部。
<强> TL; DR:强>
在 Unix 类平台上,将npm run env --
添加到您的命令; e.g:
npm run env -- mocha --recursive test/**/*.js --compilers js:babel-register
此不仅可以仅通过名称调用依赖CLI,还可以在使用npm
或{{1}时完全复制幕后npm test
设置的环境}。
可悲的是,这种方法在Windows上无法运行。
对于Windows解决方案,请继续阅读便利别名(包括每会话一次的环境配置命令)和背景信息。
有两种(不是相互排斥的)方法来制作npm项目的依赖关系&#39; CLI可以通过shell中的名称来调用:
Frxstrem's helpful answer为类似Unix的平台上的(a)提供不完整的解决方案;但是,可能,这取决于您的具体需求
它不完整,因为它只是将包含(符号链接)依赖CLI的目录添加到npm run-script <script-defined-in-package.json>
,而不执行调用$PATH
或npm test
时发生的所有其他环境修改。 / p>
请注意,以下所有解决方案均基于npm run-script <script-defined-in-package.json
,这可确保设置所有必需的环境变量,就像在项目预定义的运行脚本时一样npm run env
文件package.json
或npm test
这些环境修改包括:
npm run-script <script>
和项目目录的$(npm prefix -g)/node_modules/npm/bin/node-gyp-bin
子目录,这是符号链接的依赖关系&#39; CLI(临时)位于./node_modules/.bin
环境变量。$PATH
环境变量,例如npm_*
以及npm_package_version
/ npm
环境。下面的两个解决方案都是 alias -based ,在(a)的情况下,它是使用脚本的更轻量级替代方案>,并且在(b)的情况下是允许修改当前shell环境的先决条件(尽管也可以使用shell函数)。
为方便起见,将这些别名添加到您的shell配置文件/初始化中 文件
(a)每次调用助手:
定义
node
允许您通过预先alias nx='npm run-script env --'
前缀来临时调用命令; e.g:
nx
(b)每会话一次配置命令:
nx mocha --recursive test/**/*.js --compilers js:babel-register
运行alias npmenv='npm run env -- $SHELL'
以使用npm环境集输入子shell ,允许直接(仅限名称)调用该子shell中的从属CLI。
换句话说,使用如下:
npmenv
(a)和(b):请注意,Windows(与类似Unix的平台上的类似POSIX的shell)不支持(直接)支持传递环境变量仅限于单个命令,因此下面的命令,即使在传递执行的特定命令(case(a))时,也总是修改会话的环境(例如(b))。
PowerShell (也适用于Unix版本):
将以下函数添加到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
(用户特定的配置文件脚本):
$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
}
}
}
(常规命令提示符,经常错误地称为&#34; DOS提示符&#34;):
创建名为cmd.exe
的批处理文件,将其放在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.
%*
和PowerShell):
对于用例(b),简单地调用cmd.exe
而不带参数;之后,您可以仅通过名称(npmenv
)调用依赖CLI。
对于用例(a),在命令前加上mocha ...
; e.g:
npmenv
警告:如上所述, npmenv mocha --recursive test/**/*.js --compilers js:babel-register
的第一次调用 - 无论是否有参数 - 总是会修改npmenv
/ %PATH%
变量以用于其余部分会议。
如果您在同一会话中切换到其他项目,请务必再次运行$env:PATH
(至少一次),但请注意,这会将其他目录添加到{{1}因此,如果不是现有项目的已安装依赖项,您仍然可能最终意外地运行以前项目的可执行文件。
从PowerShell中,您实际上可以组合这两个解决方案,以获得不同的(a)和(b)功能:将上面的npmenv
文件定义为一个独特的命令(使用您只使用带有参数(a)的的不同名称,例如%PATH%
),并重新定义PowerShell函数,以作为无参数环境修改的唯一补码(b)。 />
这是有效的,因为PowerShell总是在子进程中运行*.cmd
个文件,这些文件不会影响当前的PowerShell会话环境。
关于问题范围和答案的说明:
OP的问题是关于在给定项目 ad-hoc的上下文中调用已安装的依赖包的CLI,仅仅是可执行名称 - 就像{{1}一样允许您执行添加到nx.cmd
文件中*.cmd
键的命令。
问题是不关于使CLI 全球可用(通过使用npm
安装它们)。
事实上,如果您想创建模块化,自包含的软件包,请不依赖于全局安装的软件包。相反,使所有依赖包成为项目的一部分:使用scripts
(对于运行时依赖性)和package.json
(仅用于开发时依赖性) - 请参阅https://docs.npmjs.com/cli/install
特别是,如果给定的CLI已经作为依赖安装,那么全局以及(可能是不同的版本)安装它不仅是多余的,而是要求关于在何时执行哪个版本的混淆。
答案 1 :(得分:3)
我已将这个小脚本~/bin/npm-cmd
保存在我的计算机上:
#!/bin/bash
PATH="$(npm bin):$PATH" "$@"
然后运行npm-cmd PROGRAM …ARGS
应首先在PROGRAM
中查找./node_modules/.bin
,然后再回到正常查找。
答案 2 :(得分:0)
注意:此答案适用于所有平台。
npm i -g mocha
mocha --recursive test/**/*.js --compilers js:babel-register
Mocha CLI documentation(滚动到使用部分)。
如果您想从CLI运行 npm 包作为可执行文件,正确的方法是通过package.json bin 条目。它允许您将项目中的文件映射为可执行文件。如果它是节点脚本,那么文件的第一行(如普通脚本应以shebang,#!/usr/bin/env node
开头。
通过在package.json bin中映射这些文件,您可以从其他软件包脚本部分调用它们,或者在使用npm install -g <package>
全局安装软件包时从cli调用它们。 bin 节点可以是将脚本名称映射到项目中的脚本文件的对象,如果要将多个脚本作为可执行文件添加到路径中,或者是您想要的单个文件的字符串路径充当您的包的可执行文件。
这实际上是你的例子中mocha使用的exact same mechanism:
如果没有这个,在全局安装时,mocha将永远不会出现在您的路径中,并且无法通过脚本部分访问。