pnpm run

别名: run-script

运行在软件包清单文件中定义的脚本。

示例#

假如你有个 watch 脚本配置在了 package.json 中,像这样:

"scripts": {
    "watch": "webpack --watch"
}

你现在可以使用 pnpm run watch 运行该脚本!很简单吧?对于那些不喜欢敲键盘而浪费时间的人要注意的另一件事是,所有脚本都会有 pnpm 命令的别名,所以最终 pnpm run watch 的简写是 pnpm watch (仅适用于那些不与已有的 pnpm 命令相同名字的脚本)。

运行多个脚本#

你可以使用正则表达式来替代脚本名称从而同时运行多个脚本。

pnpm run "/<regex>/"

运行所有以 watch: 开头的脚本。

pnpm run "/^watch:.*/"

选择器必须写成正则表达式字面量(即用斜杠括起来)并加上引号,以防 Shell 对其进行破坏。普通字符串始终被视为字面意义上的脚本名称;若脚本名称与该参数完全匹配,则其优先级高于正则表达式匹配。

匹配不包含锚定限制,因此 "/build:.*/" 也能匹配 prebuild:web。当需要精确匹配前缀时,请使用 ^ 和 $ 来限定模式。

匹配的脚本按字典顺序执行,因此无论它们在 package.json 中以何种顺序出现,最终的选择结果都是确定的。若要严格按顺序逐个运行它们,请添加 --sequential。

不支持正则表达式标志:执行 pnpm run "/^build:.*/i" 会失败,并报错 ERR_PNPM_UNSUPPORTED_SCRIPT_COMMAND_FORMAT。

详情#

除了 shell 先前存在的 PATH, pnpm run 也包括在 PATH 中的 node_modules/.bin 提供的 scripts。这意味着,只要你安装了一个包,你就可以像常规命令一样在脚本中使用它。例如,如果你已经安装了 eslint,你可以这样写一个脚本:

"lint": "eslint src --fix"

即使 eslint 没有在你的 shell 中全局安装,它也会运行。

对于工作空间, <workspace root>/node_modules/.bin 也会被添加到 到 PATH 中,因此如果在工作空间根目录中安装了工具,则可以在工作空间中任何软件包的 scripts 中调用它。

运行环境#

pnpm 会自动为执行的脚本创建一些环境变量。这些环境变量可用于获取有关正在运行的进程的上下文信息。

以下是 pnpm 会创建的环境变量:

  • npm_command - 包含已执行命令的名称。如果执行的命令是 pnpm run,那么这个变量的值就是“run-script”。

配置项#

run 命令的选项都应被列在脚本名称之前。脚本名称后列出的options将传递给执行的脚本。

例如下面这些都将使用 --silent 选项运行 pnpm CLI:

pnpm run --silent watch
pnpm --silent run watch
pnpm --silent watch

脚本名称后的任何参数都将添加到执行的脚本中。所以如果 watch 运行 webpack --watch,那么这个命令:

pnpm run watch --no-color

将运行:

webpack --watch --no-color

--recursive, -r#

这会从每个包的 "scripts" 字段中运行任意一个命令。如果包没有该命令,则会跳过该命令。如果所有包都没有该命令,则该命令将失败。

--if-present#

可以使用 --if-present 标志避免遇到脚本未定义导致通过非零的退出代码退出的情况。这使你可以在不中断执行链的情况下运行可能未定义的脚本。

--no-bail#

即使其中一个匹配的脚本失败,也要继续运行其余脚本。如果任何脚本执行失败,该命令仍会以非零退出码退出。

--parallel#

完全忽略并发和拓扑排序,在所有匹配的包中立即运行给定的脚本 并输出前缀流。对于许多包中长时间运行的进程,这是首选标志,例如漫长的构建进程。

--sequential, -s#

添加于: v11.14.0

逐个运行选定的脚本。这会将 --workspace-concurrency 强制设为 1,从而确保由 正则表达式选择器 匹配的脚本绝不会发生重叠——无论是在不同的工作区包之间,还是在同一个包内部。

pnpm run --sequential "/^build:.*/"

在递归运行模式下,该操作会对工作区内各项目之间以及每个项目内部的脚本进行序列化处理。 --sequential 的优先级高于 --parallel:只要设置了该标志,并发数就会被锁定为 1,无论这两个标志出现的顺序如何。

注意

对于 pnpm run,-s 是 --sequential 的简写。在 CLI 的其他所有地方,-s 仍然是 --reporter=silent 的简写。长格式 --silent 在所有命令中均不受影响。

--stream#

立即从子进程流式传输输出,并以原始包目录为前缀。这使得不同包的输出可以交错。

--aggregate-output#

聚合并行运行的子进程的输出,并且仅在子进程完成时打印输出。它使在运行 pnpm -r <command> 时使用 --parallel 或 --workspace-concurrency=<number> 后读取大日志更容易(尤其是在 CI 上)。仅支持 --reporter=append-only。

--resume-from <package_name>#

从特定项目恢复执行。如果你正在使用大型工作空间,并且想要在不运行先前项目的情况下从特定项目重新启动构建,那么这可能非常有用。

--report-summary#

将脚本执行的结果记录到 pnpm-exec-summary.json 文件中。

pnpm-exec-summary.json的示例:

{
  "executionStatus": {
    "/Users/zoltan/src/pnpm/pnpm/cli/command": {
      "status": "passed",
      "duration": 1861.143042
    },
    "/Users/zoltan/src/pnpm/pnpm/cli/common-cli-options-help": {
      "status": "passed",
      "duration": 1865.914958
    }
  }

status 的可能值为:“passed”、“queued”、“running”。

--reporter-hide-prefix#

从并行运行的子进程的输出中隐藏工作空间前缀,并且仅打印原始输出。如果你在 CI 上运行并且输出必须是不带任何前缀的特定格式(例如 GitHub Actions annotations),这会很有用。仅支持 --reporter=append-only。

--filter <package_selector>#

阅读更多有关过滤的内容。

pnpm-workspace.yaml 设置#

enablePrePostScripts#

  • 默认值:true
  • 类型:Boolean

当 true 时,pnpm 将自动运行任何前/后脚本。因此运行 pnpm foo 将类似于运行 pnpm prefoo pnpm foo pnpm postfoo。

scriptShell#

  • 默认值: null
  • 类型:路径

使用 pnpm run 命令运行脚本所使用的 shell。

例如,在 Windows 系统上强制使用 Git Bash:

pnpm config set scriptShell "C:\\Program Files\\git\\bin\\bash.exe"

shellEmulator#

  • 默认值: false
  • 类型:Boolean

当为 true 时,pnpm 将使用 [类 bash shell][bash-like shell] 的 JavaScript 实现来 执行脚本。

该选项简化了跨平台运行脚本。例如,默认情况下,下述脚本将在非 POSIX 标准兼容系统下运行失败:

"scripts": {
  "test": "NODE_ENV=test node test.js"
}

但是,如果 shellEmulator 设置为 true,它将适用于所有平台。

注意

Node.js 22 或更高版本支持在没有 pnpm 帮助的情况下运行脚本。对于上面的例子,你可以使用“node --run test”运行“test”脚本。但是,shellEmulator 选项对此没有影响。依赖 POSIX 特性的脚本需要运行 pnpm run 而不是node --run 才能在不兼容 POSIX 的环境中工作。