通过白名单解决 pnpm i 报错 Ignored build scripts
问题背景
在执行 pnpm dev 或 pnpm install 命令时,遇到以下错误:
bash
[ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: core-js@3.45.1, esbuild@0.25.1
Run "pnpm approve-builds" to pick which dependencies should be allowed to run scripts.
此错误表明 pnpm 的安全策略阻止了 core-js 和 esbuild 包的构建脚本执行,导致依赖安装失败。
解决方案
工作空间级别配置(pnpm-workspace.yaml)
在项目根目录创建或修改 pnpm-workspace.yaml 文件,添加 allowBuilds 配置:
yaml
allowBuilds:
core-js: true
esbuild: true
配置说明:
allowBuilds是 pnpm 的官方白名单机制- 将需要运行构建脚本的包名设为
true,允许其执行安装脚本 - 此配置在工作空间级别生效,适用于所有子包
包级别配置(package.json)
在 package.json 中添加 pnpm.onlyBuiltDependencies 配置:
json
{
"pnpm": {
"onlyBuiltDependencies": [
"core-js",
"esbuild"
]
}
}
配置说明:
onlyBuiltDependencies指定仅允许这些包运行构建脚本- 此配置在包级别生效,让策略更加清晰可见
- 确保自动化安装不会被 pnpm 的安全策略拦截
配置原理
pnpm 构建脚本安全机制
pnpm 默认会拦截所有包的构建脚本(postinstall、preinstall 等),这是一种安全措施,防止恶意包在安装时执行危险代码。
当首次安装包含构建脚本的包时,pnpm 会提示用户确认是否允许执行。但在自动化环境(如 CI/CD)中,这种交互式确认会导致安装失败。
双重配置的优势
| 配置层级 | 文件位置 | 作用范围 | 优势 |
|---|---|---|---|
| 工作空间级别 | pnpm-workspace.yaml |
所有子包 | 统一管理,一次配置全局生效 |
| 包级别 | package.json |
当前包 | 清晰声明依赖,便于维护 |
为什么 core-js 和 esbuild 会出现问题?
1. esbuild:为了获取底层原生二进制文件(核心刚需)
- 为什么需要脚本 :
esbuild是用 Go 语言编写的,为了达到极高的编译速度,它在运行时并不依赖 Node.js 引擎,而是依赖针对不同操作系统(Windows、macOS、Linux)和 CPU 架构(x86、ARM64)预编译的原生二进制文件 。在安装时,esbuild的postinstall脚本会检测你当前的系统环境,并自动去拉取或链接对应的可执行文件(例如@esbuild/darwin-arm64)。 - 被拦截的后果 :如果这个脚本被 pnpm 阻止,底层的二进制文件就不会被正确下载或配置。当你尝试启动项目(比如使用依赖
esbuild的 Vite 时),就会因为找不到底层的执行程序而直接崩溃报错。
2. core-js:为了输出控制台提示信息(非核心功能)
- 为什么需要脚本 :
core-js是 JavaScript 生态中最基础的 Polyfill 库之一。由于这是一个个人维护且被极其广泛使用的开源项目,作者在项目的postinstall阶段加入了一段脚本,用于在依赖安装完成后,在终端打印一条包含"求职"或"赞助(Funding)"信息的提示,有时也会附带一些简单的环境检查。 - 被拦截的后果 :如果不执行这段脚本,
core-js的核心代码其实完全可以正常工作 。但只要该包声明了postinstall动作,pnpm 的安全机制就会一视同仁地将其捕获,并抛出[ERR_PNPM_IGNORED_BUILDS]错误,强制要求开发者确认。