# npm exec

从 npm 包运行命令

# 概要

npm exec -- <pkg>[@<version>] [args...]
npm exec --package=<pkg>[@<version>] -- <cmd> [args...]
npm exec -c '<cmd> [args...]'
npm exec --package=foo -c '<cmd> [args...]'

alias: x

注意

这个命令不支持工作空间。

# 描述

这个命令允许你从 npm 包(本地安装或远程获取)中运行任意命令。在类似于通过 npm run 运行它的环境中。

运行时不带位置参数或 --call,这允许您在运行 package.json 脚本的同一类 shell 环境中交互式地运行命令。当标准输入是 TTY 时,CI 环境不支持交互模式,以防止挂起。

--package 选项指定的任何包将在被执行命令的 PATH 中提供,以及任何本地安装的包可执行文件。可以多次指定 --package 选项,以便在所有指定包都可用的环境中执行所提供的命令。

如果任何被请求的包没有出现在本地项目依赖项中,那么它们会被安装到 npm 缓存中的一个文件夹中,这个文件夹会被添加到执行进程的 PATH 环境变量中。会打印一个提示符(可以通过提供 --yes--no 来阻止它)。

没有说明符的包名将与本地项目中存在的任何版本匹配。带有说明符的包名只有在与本地依赖项具有完全相同的名称和版本时才被认为是匹配的。

如果没有提供 -c--call 选项,则使用位置参数生成命令字符串。如果没有提供 --package 选项,那么 npm 将尝试根据以下启发式方法,从作为第一个位置参数提供的包说明符中确定可执行文件名:

  • 如果包在 package.json 中的 bin 字段中有单个条目,或者如果所有条目都是相同命令的别名,那么将使用该命令。
  • 如果包有多个 bin 条目,并且其中一个条目匹配 name 字段中未限定范围的部分,那么将使用该命令。
  • 如果这没有产生一个选项(要么因为没有 bin 条目,要么它们都不匹配包的 name),则 npm exec 退出并返回一个错误。

要运行一个非命名二进制文件,请指定一个或多个 --package 选项,这将防止 npm 从第一个命令参数推断出包。

# npx vs npm exec

当通过 npx 二进制运行时,所有标志和选项必须在任何位置参数之前设置。当通过 npm exec 运行时,一个双连字符 -- 标志可以用来抑制 npm 对应该发送给执行命令的开关和选项的解析。

例如:

$ npx foo@latest bar --package=@npmcli/foo

在这种情况下,npm 将解析 foo 包名,并运行如下命令:

$ foo bar --package=@npmcli/foo

由于 --package 选项出现在位置参数之后,因此它被视为所执行命令的参数。

相反,由于 npm 的参数解析逻辑,运行这个命令是不同的:

$ npm exec foo@latest bar --package=@npmcli/foo

在这种情况下,npm 将首先解析 --package 选项,解析 @npmcli/foo 包。然后,它将在该上下文中执行以下命令:

$ foo@latest bar

建议使用双连字符显式地告诉 npm 停止解析命令行选项和开关。因此,以下命令相当于上面的 npx 命令:

$ npm exec -- foo@latest bar --package=@npmcli/foo

# 配置

# package

  • Default:
  • Type: String (可以设置多次)

npm exec 安装的一个或多个软件包

# call

  • Default: ""
  • Type: String

可选伴随选项 npm execnpx 允许指定与已安装的包一起运行的自定义命令。

npm exec --package yo --package generator-node --call "yo node" 

# workspace

  • Default:
  • Type: String (可以设置多次)

启用在当前项目的已配置工作区的上下文中运行命令,同时通过仅运行此配置选项定义的工作区进行过滤。

workspace 配置的有效值如下:

  • 工作区名称
  • 工作区目录的路径
  • 父工作区目录的路径(将导致选择该文件夹中的所有工作区)

npm init 命令设置时,可以将其设置为尚不存在的工作空间的文件夹,以创建文件夹并将其设置为项目中的全新工作空间。

此值不会导出到子进程的环境中。

# workspaces

  • Default: null
  • Type: null or Boolean

设置为 true 将在所有配置的工作区中运行该命令。

显式地将此设置为 false 将导致如下命令 install 完全忽略工作空间。当没有显式设置时:

  • node_modules 树上操作的命令 (install, update, etc.) 时,将把工作区链接到 node_modules 文件夹中。做其他事情的命令 (test, exec, publish, etc.) 将在根项目上操作,除非在 workspace 配置中指定了一个或多个工作空间。

此值不会导出到子进程的环境中。

# include-workspace-root

  • Default: false
  • Type: Boolean

当为某个命令启用工作区时,请包含工作区根目录。

当为 false 时,通过 workspace 配置指定单个工作空间,或通过 workspaces 标志指定所有工作空间,将导致 npm 仅在指定的工作空间上运行,而不是在根项目上运行。

此值不会导出到子进程的环境中。

# 例子

tap 使用提供的参数运行本地依赖项中的版本:

$ npm exec -- tap --bail test/foo.js
$ npx tap --bail test/foo.js

通过指定 --package 选项来运行与包名匹配的命令:

$ npm exec --package=foo -- bar --bar-argument
# ~ or ~
$ npx --package=foo bar --bar-argument

在当前项目的上下文中运行任意 shell 脚本:

$ npm x -c 'eslint && say "hooray, lint passed"'
$ npx -c 'eslint && say "hooray, lint passed"'

# 工作空间的支持

你可以使用 workspaceworkspaces config 来在指定的工作区上下文中从 npm 包(本地安装或远程获取)运行任意命令。如果没有提供位置参数或 --call 选项,它将在每个配置的工作空间的上下文中每次打开一个交互式子 shell。

给定一个带有配置工作空间的项目,例如:

.
+-- package.json
`-- packages
   +-- a
   |   `-- package.json
   +-- b
   |   `-- package.json
   `-- c
       `-- package.json

假设在根级别 package.json 文件中正确设置了工作区配置。例句:

{
    "workspaces": [ "./packages/*" ]
}

当使用 workspaces 配置选项时,你可以在每个配置的工作空间的上下文中从包中执行任意命令,在这个例子中,我们使用 eslint 来检测每个工作空间文件夹中的任何js文件:

npm exec --ws -- eslint ./*.js

# 过滤工作区

也可以使用工作区配置以及名称或目录路径在单个 workspace 中执行命令:

npm exec --workspace=a -- eslint ./*.js

还可以多次指定 workspace 配置,以便在多个工作空间的上下文中运行特定的脚本。当在命令行中为 workspace 配置定义值时,也可以使用 -w 作为速记,例如:

npm exec -w a -w b -- eslint ./*.js

最后一个命令将在 ./packages/a./packages/b 文件夹中运行 eslint 命令。

# 与旧 npx 版本的兼容性

npx 二进制文件在 npm v7.0.0 中被重写,并且当时 npx 不推荐使用独立包。 npx 使用 npm exec 命令而不是单独的参数解析器和安装过程,并提供一些功能来保持与以前版本中接受的参数的向后兼容性。

# 这导致其功能发生了一些变化:

  • 可以提供任何 npm 配置值。
  • 为了防止错误输入包名造成的安全和用户体验问题,npx 在安装任何东西之前都会提示。使用 -y--yes 选项禁止此提示。
  • --no-install 选项已弃用,将被转换为 --no
  • 删除了 Shell 回退功能,因为这是不可取的。
  • -p 参数在 npm 中是 --parseable 的简写,但在 npx 中是 --package 的简写。这是维护的,但只针对 npx 可执行文件。
  • 删除 --ignore-existing 选项。本地安装的容器总是存在于执行的进程 PATH 中。
  • --npm 选项被移除。npx 将始终使用它附带的 npm
  • 删除了 --node-arg-n 选项。
  • --always-spawn 选项是多余的,因此被删除。
  • --shell 选项被替换为 --script-shell,但在 npx 可执行文件中保持向后兼容性。

# 关于缓存的注意事项

当使用指定的包名时,npm cli 会使用它的内部包缓存。您可以使用下面的代码来更改 cli 使用这个缓存的方式和时间。有关缓存如何工作的更多信息,请参阅 npm cache

# prefer-online

  • Default: false
  • Type: Boolean

强制检查包的陈旧性,使 cli 立即查找更新,即使包已经在缓存中。

# prefer-offline

  • Default: false
  • Type: Boolean

绕过包的陈旧性检查。服务器仍然会请求丢失的数据。如果要强制完全离线模式,请使用 offline

# offline

  • Default: false
  • Type: Boolean

强制完全离线模式。没有本地缓存的任何包都将导致错误。

# workspace

  • Default:
  • Type: String (可以设置多次)

启用在当前项目的已配置工作区的上下文中运行命令,同时通过仅运行此配置选项定义的工作区进行过滤。

workspace 配置的有效值如下:

  • 工作区名称
  • 工作区目录的路径
  • 父工作区目录的路径(将导致选择该文件夹中的所有工作区)

此值不会导出到子进程的环境中。

# workspaces

  • Alias: --ws
  • Type: Boolean
  • Default: false

在当前项目的所有配置工作区的上下文中运行脚本。

Last Updated: 4/25/2023, 9:49:29 AM