在没有“脚本”条目的情况下实现“npm run x”行为?
要在已安装的node_modules
的“上下文”中运行节点命令,可以在package.json
的scripts
字段中input一个条目。 例如:
... "scripts": { "test": "mocha --recursive test/**/*.js --compilers js:babel-register" } ...
然后我可以在我的项目根目录中键入npm run test
,并且运行mochatesting(通过调用安装在node_modules/mocha/bin
的mocha二进制文件)。
有没有办法实现完全相同的行为,但不创build脚本条目? 例如,一次性“脚本”?
我想像下面这样,等同于npm run test
:
npm cmd mocha --recursive test/**/*.js --compilers js:babel-register
有没有办法做到这一点?
注:我应该澄清,我正在寻找真正的等值。 也就是说,我的命令应该能够访问其他脚本命令等。我知道你总是可以使用节点和node_modules中的二进制文件的path调用二进制文件,但这不是一个适当的解决scheme。
注意:这个回答解决了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解决scheme,可以读取便利别名(包括每个会话一次的环境configuration命令)和背景信息。
有两种(不是互斥的) 方法来使npm项目的依赖关系的CLI可以通过shell的名字来调用 :
- (a)使用传递命令的per-invocation helper命令 。
- (b)运行一次一次的会话命令(暂时)修改您的环境 。
Frxstrem的有用答案为(a)类Unix平台提供了一个不完整的解决scheme; 但是,根据您的具体需求,这可能就足够了。
这是不完整的,因为它只是将包含从属CLI的(符号链接)前缀到$PATH
,而不执行在调用npm test
或npm run-script <script-defined-in-package.json
时发生的所有其他环境修改npm run-script <script-defined-in-package.json
。
Unix方便和Windows解决scheme
请注意, 下面的所有解决scheme都基于npm run env
,它确保所有必需的环境variables都已设置,就像在项目的package.json
文件中使用npm test
或npm run-script <script>
预定义的npm run-script <script>
。
这些环境修改包括:
- 在
$(npm prefix -g)/node_modules/npm/bin/node-gyp-bin
和项目目录的./node_modules/.bin
子目录(这是依赖项的CLI所在的符号链接所在的位置)(临时)./node_modules/.bin
加上$PATH
环境variables。 - 定义反映项目设置的许多
npm_*
环境variables,例如npm_package_version
以及npm
/node
环境。
Unix类平台的便捷解决scheme:
下面的两个解决scheme都是基于别名的 ,在(a)的情况下是使用脚本的更轻量级的替代方法,而在(b)的情况下是允许修改当前shell环境的先决条件shell函数也可以使用)。
为了方便起见, 将这些别名添加到您的shellconfiguration文件/初始化文件中 。
(a)每个调用助手:
定义
alias nx='npm run-script env --'
允许你简单地通过预先计算nx
来调用你的命令。 例如:
nx mocha --recursive test/**/*.js --compilers js:babel-register
(b)一次一个会话configuration命令:
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; eg, `mocha ...` # ... run your project-specific commands exit # exit the child shell before you switch to a different project
Windows解决scheme:
(a) 和 (b) :注意,Windows(不像Unix类似的类似于POSIX的shell)并不直接支持将环境variables作为范围传递给一个命令,所以下面的命令即使通过一个特定的命令来执行(情况(a)),总是也修改会话的环境(情况(b))。
PowerShell (也适用于Unix版本):
将以下函数添加到$PROFILE
(用户特定的configuration文件脚本)中:
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提示符”):
创build一个名为npmenv.cmd
的batch file,将其放置在%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
的第一次调用(无论是否带有参数) npmenv
修改会话剩余部分的%PATH%
/ $env:PATH
variables。
如果您在同一个会话中切换到另一个项目,请务必再次运行npmenv
(至less一次),但请注意,这会将其他目录加到%PATH%
,因此您仍然可能最终意外地运行了以前的项目可执行文件它不是当前项目的已安装依赖项。
从PowerShell中,实际上可以结合使用这两种解决scheme来获得截然不同的(a)和(b)function:将上面的*.cmd
文件定义为不同的命令(使用不同的名称,如nx.cmd
) (a),并重新定义PowerShell函数作为无variables环境修改补充(b)。
这是有效的,因为PowerShell总是在子进程中运行*.cmd
文件,不会影响当前的PowerShell会话环境。
问题的范围和这个答案的注释:
OP的问题是关于在特定项目的上下文中通过单纯的可执行名称调用已经安装的依赖包的CLI – 就像npm
允许您在添加到package.json
的scripts
键中的命令一样文件。
问题不在于使CLI 全局可用 (通过使用npm install -g
安装它们)。
事实上,如果你想编写模块化,自包含的软件包,不要依赖于全局安装的软件包。 相反,使所有相关软件包的一部分你的项目 :使用npm install --save
(运行时依赖)和npm install --save-dev
(仅用于开发时间依赖) – 请参阅https://docs.npmjs.com/ CLI /安装
特别是,如果一个给定的CLI已经作为一个依赖项安装,那么全局安装(可能是一个不同的版本)不仅是多余的,而且要求在什么时候执行哪个版本。
我在计算机上保存了这个小脚本作为~/bin/npm-cmd
:
#!/bin/bash PATH="$(npm bin):$PATH" "$@"
然后运行npm-cmd PROGRAM … ARGS
应该首先在./node_modules/.bin
查找PROGRAM
,然后再回到正常查找。
注意:这个答案适用于所有平台。
npm i -g mocha
mocha --recursive test/**/*.js --compilers js:babel-register
摩卡CLI文档 (滚动到使用部分)。
如果你想从CLI运行一个npm包作为可执行文件,正确的方法是通过package.json bin条目。 它允许您将项目中的文件映射为可执行文件。 与普通脚本一样,文件的第一行应该以shebang , #!/usr/bin/env node
作为节点脚本。
通过将这些文件映射到您的package.json bin中,您将能够从其他软件包脚本部分调用它们,或者在使用npm install -g <package>
全局npm install -g <package>
软件包时,从cli调用它们。 bin节点可以是一个对象,如果要将多个脚本作为可执行文件添加到path中,或将单个文件的stringpath作为您的包的可执行文件。
这实际上是摩卡在你的例子中使用的完全相同的机制 :
如果没有这一点,摩卡将永远不会在你的path全局安装,而不会通过你的脚本部分访问。