主题
Execa
Execa 是对 node:child_process 的 Promise 化封装,用于从 Node.js 运行外部命令。它提供结构化结果、详细错误、可靠的本地二进制解析和跨平台处理。
适合构建脚本、开发工具和 CLI;只需基础子进程控制或需要精确理解进程模型时,直接使用原生 child_process。
安装与执行
bash
pnpm add execats
import { execa } from 'execa'
const { stdout } = await execa`git status --short`
console.log(stdout)模板标签会将插值作为独立参数传递,不需要自行拼接或转义:
ts
import { execa } from 'execa'
const outputDir = 'dist preview'
await execa`mkdir -p ${outputDir}`不要把不可信输入拼进 shell: true 的命令字符串。默认使用模板标签或命令与参数分离的形式。
常用选项
ts
import { execa } from 'execa'
const result = await execa('pnpm', ['build'], {
cwd: process.cwd(),
preferLocal: true,
reject: false,
all: true,
})
if (result.exitCode !== 0) {
console.error(result.all)
}cwd:指定命令工作目录。preferLocal:优先执行项目node_modules/.bin中的命令。reject: false:非零退出码时返回结果而非抛出异常。all: true:合并保留stdout与stderr的输出顺序。stdio: 'inherit':将子进程输出直接交给当前终端,适合交互式命令。
默认情况下,非零退出码会抛出 ExecaError。异常中包含命令、工作目录、退出码、stdout 与 stderr,应记录这些字段而不是只输出错误消息。
结束子进程
长时间运行的命令应显式支持取消:
ts
import { execa } from 'execa'
const controller = new AbortController()
const task = execa({ cancelSignal: controller.signal })`pnpm dev`
setTimeout(() => controller.abort(), 5_000)
await task取消后仍需处理 Promise 拒绝;不要只终止父进程而遗留子进程。
