news 2026/4/16 14:11:51

解决 pnpm 构建脚本被阻止(Ignored build scripts)的问题

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
解决 pnpm 构建脚本被阻止(Ignored build scripts)的问题

解决 pnpm 构建脚本被阻止的问题

当使用 pnpm 时出现 "Ignored build scripts" 警告,这是因为 pnpm 的安全策略阻止了某些包的构建脚本执行。这是 pnpm 的一个安全特性,防止恶意包执行潜在危险的构建脚本。


Ignored build scripts: esbuild.

Run "pnpm approve-builds" to pick which dependencies should be allowed to run scripts.


一、问题原因分析

1.1 为什么会发生?

  • 安全策略:pnpm 默认阻止包的构建脚本(如postinstallpreinstall等)

  • 依赖包行为:某些包(如esbuild)在安装后需要运行构建脚本

  • 许可列表:pnpm 需要明确的许可才能运行这些脚本

1.2 常见触发包

esbuild # 需要编译原生模块 sharp # 图像处理库 bcrypt # 密码加密 sqlite3 # SQLite 数据库绑定 node-sass # Sass 编译器

二、解决方案

2.1 方法一:批准特定包的构建脚本(推荐)

bash

# 批准单个包 pnpm install --ignore-scripts=false esbuild # 或批准所有包(不推荐,有安全风险) pnpm config set ignore-scripts false

2.2 方法二:使用 pnpm 的命令行工具

bash

# 1. 查看需要批准的包 pnpm install # 会显示哪些包的构建脚本被阻止 # 2. 运行批准命令 pnpm approve-builds # 这会交互式地询问您要批准哪些包 # 3. 或者一次性批准所有(谨慎使用) pnpm approve-builds --all

2.3 方法三:项目级配置

在项目根目录创建.npmrc文件:

ini

# .npmrc # 允许 esbuild 运行构建脚本 public-hoist-pattern[]=*esbuild* # 或允许所有包 ignore-scripts=false

或通过命令行设置:

bash

# 仅为当前项目设置 pnpm config set ignore-scripts false # 全局设置(影响所有项目) pnpm config set --global ignore-scripts false

2.4 方法四:使用 package.json 配置

json

{ "name": "my-vue3-app", "version": "1.0.0", "pnpm": { "patchedDependencies": { "esbuild@0.19.0": "patches/esbuild@0.19.0.patch" }, "overrides": { "esbuild": "0.19.0" } }, "scripts": { "postinstall": "pnpm rebuild esbuild" } }

三、Vue3 项目的完整解决方案

3.1 针对 Vue3 + Vite 项目的配置

步骤 1:创建 pnpm 配置文件

yaml

# .pnpmfile.cjs module.exports = { hooks: { readPackage(pkg) { // 允许 esbuild 运行脚本 if (pkg.name === 'esbuild') { pkg.scripts = pkg.scripts || {}; } // 允许其他需要构建的包 const allowedPackages = [ 'esbuild', '@esbuild/darwin-x64', '@esbuild/linux-x64', '@esbuild/win32-x64', 'sharp', 'bcrypt' ]; if (allowedPackages.includes(pkg.name)) { console.log(`允许 ${pkg.name} 运行构建脚本`); } return pkg; } } };

步骤 2:创建项目级配置

ini

# .npmrc # pnpm 配置 shamefully-hoist=true public-hoist-pattern[]=*esbuild* public-hoist-pattern[]=*vite* public-hoist-pattern[]=*vue* auto-install-peers=true strict-peer-dependencies=false # 允许运行构建脚本 ignore-scripts=false

步骤 3:创建安装脚本

bash

#!/bin/bash # install.sh echo "🚀 安装依赖并批准必要的构建脚本..." # 安装依赖,跳过脚本执行 pnpm install --ignore-scripts # 批准必要的包 pnpm approve-builds --package esbuild pnpm approve-builds --package @esbuild/darwin-x64 pnpm approve-builds --package @esbuild/linux-x64 pnpm approve-builds --package @esbuild/win32-x64 # 如果需要,批准更多包 # pnpm approve-builds --package sharp # pnpm approve-builds --package bcrypt # 重新安装并运行脚本 echo "🔄 重新安装并运行构建脚本..." pnpm install echo "✅ 安装完成!"

3.2 Vue3 + TypeScript + Vite 的完整示例

项目结构:

text

vue3-project/ ├── .npmrc ├── .pnpmfile.cjs ├── package.json ├── pnpm-workspace.yaml ├── install.sh └── src/

package.json配置示例:

json

{ "name": "vue3-vite-app", "private": true, "version": "1.0.0", "type": "module", "scripts": { "dev": "vite", "build": "vue-tsc && vite build", "preview": "vite preview", "install:safe": "./install.sh", "postinstall": "pnpm rebuild esbuild && pnpm rebuild @esbuild/darwin-x64", "setup": "pnpm install --ignore-scripts && pnpm approve-builds --all && pnpm install" }, "dependencies": { "vue": "^3.3.4", "vue-router": "^4.2.0", "pinia": "^2.1.0" }, "devDependencies": { "@vitejs/plugin-vue": "^4.2.3", "@vue/tsconfig": "^0.4.0", "esbuild": "^0.19.0", "typescript": "^5.0.2", "vite": "^4.3.9", "vue-tsc": "^1.4.2" }, "packageManager": "pnpm@8.6.0" }

pnpm-workspace.yaml(如果使用 monorepo):

yaml

packages: # 所有包都在 packages/ 目录下 - 'packages/**' # 不包括 tests 目录 - '!**/test/**'

四、针对不同场景的解决方案

4.1 开发环境解决方案

方案 A:宽松策略(适合个人项目)

bash

# 1. 禁用脚本阻止 pnpm config set ignore-scripts false # 2. 安装依赖 pnpm install # 3. 如果需要,恢复安全设置 pnpm config set ignore-scripts true

方案 B:选择性批准(适合团队项目)

创建scripts/setup-dev.js

javascript

// scripts/setup-dev.js const { execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); // 需要批准的包列表 const ALLOWED_PACKAGES = [ 'esbuild', '@esbuild/darwin-x64', '@esbuild/linux-x64', '@esbuild/win32-x64', '@esbuild/darwin-arm64', '@esbuild/linux-arm64' ]; console.log('🔧 设置开发环境...'); try { // 检查是否使用 pnpm const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8')); const isPnpm = packageJson.packageManager?.includes('pnpm') || fs.existsSync('pnpm-lock.yaml'); if (!isPnpm) { console.log('📦 使用 npm/yarn,无需特殊处理'); process.exit(0); } console.log('📦 检测到使用 pnpm,处理构建脚本...'); // 方法1:使用 approve-builds console.log('✅ 批准必要的构建脚本...'); ALLOWED_PACKAGES.forEach(pkg => { try { execSync(`pnpm approve-builds --package ${pkg}`, { stdio: 'inherit' }); } catch (error) { console.log(`⚠️ 无法批准 ${pkg}: ${error.message}`); } }); // 方法2:重新安装 console.log('🔄 重新安装依赖...'); execSync('pnpm install', { stdio: 'inherit' }); console.log('🎉 开发环境设置完成!'); } catch (error) { console.error('❌ 设置失败:', error.message); process.exit(1); }

package.json中:

json

{ "scripts": { "prepare": "node scripts/setup-dev.js", "dev": "vite" } }

4.2 CI/CD 环境解决方案

GitHub Actions 示例:

yaml

# .github/workflows/ci.yml name: CI on: push: branches: [main, develop] pull_request: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' cache: 'pnpm' - name: Setup pnpm uses: pnpm/action-setup@v2 with: version: 8 - name: Install dependencies run: | # 允许所有构建脚本(CI环境相对安全) pnpm config set ignore-scripts false # 安装依赖 pnpm install # 恢复安全设置(可选) pnpm config set ignore-scripts true - name: Build run: pnpm run build - name: Test run: pnpm run test

4.3 Docker 环境解决方案

Dockerfile:

dockerfile

# 使用 Node.js 官方镜像 FROM node:18-alpine # 安装 pnpm RUN npm install -g pnpm WORKDIR /app # 复制配置文件 COPY package.json pnpm-lock.yaml .npmrc ./ # 安装依赖,允许构建脚本 RUN pnpm config set ignore-scripts false && \ pnpm install --frozen-lockfile && \ pnpm config set ignore-scripts true # 复制源代码 COPY . . # 构建应用 RUN pnpm run build # 暴露端口 EXPOSE 3000 # 启动命令 CMD ["pnpm", "preview"]

五、常见问题排查

5.1 问题:pnpm approve-builds命令不存在

bash

# pnpm 6.x 版本需要安装插件 pnpm add -g @pnpm/plugin-commands-script-runners # 或升级 pnpm 到 7.x 或更高版本 npm install -g pnpm@latest # 检查版本 pnpm --version

5.2 问题:特定包仍然无法构建

针对 esbuild 的特殊处理:

bash

# 1. 清理缓存 pnpm store prune # 2. 删除 node_modules rm -rf node_modules # 3. 手动下载并构建 esbuild PNPM_IGNORE_SCRIPTS=false pnpm add esbuild # 4. 或使用替代安装方法 npm install esbuild --ignore-scripts=false

5.3 问题:跨平台兼容性

创建平台特定的安装脚本:

javascript

// scripts/install-platform.js const os = require('os'); const { execSync } = require('child_execute'); const platform = os.platform(); const arch = os.arch(); console.log(`平台: ${platform}-${arch}`); const PLATFORM_PACKAGES = { 'darwin-x64': ['@esbuild/darwin-x64'], 'darwin-arm64': ['@esbuild/darwin-arm64'], 'linux-x64': ['@esbuild/linux-x64'], 'linux-arm64': ['@esbuild/linux-arm64'], 'win32-x64': ['@esbuild/win32-x64'], 'win32-arm64': ['@esbuild/win32-arm64'] }; const key = `${platform}-${arch}`; const packages = PLATFORM_PACKAGES[key] || []; if (packages.length > 0) { console.log(`批准平台特定包: ${packages.join(', ')}`); packages.forEach(pkg => { try { execSync(`pnpm approve-builds --package ${pkg}`, { stdio: 'inherit' }); } catch (error) { console.log(`警告: 无法批准 ${pkg}`); } }); }

六、安全考虑和最佳实践

6.1 安全建议

  1. 最小权限原则:只批准必要的包

  2. 审查包来源:只批准来自可信源的包

  3. 定期更新:保持包的最新版本

  4. 使用锁文件:确保依赖版本一致

6.2 推荐的批准列表

对于 Vue3 项目,通常只需要批准:

bash

# 核心构建工具 pnpm approve-builds --package esbuild # 平台特定 esbuild pnpm approve-builds --package @esbuild/darwin-x64 pnpm approve-builds --package @esbuild/linux-x64 pnpm approve-builds --package @esbuild/win32-x64 # 可选:如果使用这些包 # pnpm approve-builds --package sharp # pnpm approve-builds --package bcrypt

6.3 完整的安全安装脚本

bash

#!/bin/bash # safe-install.sh set -e # 遇到错误时停止 echo "🔒 安全安装依赖..." # 1. 只安装,不运行脚本 echo "📦 安装依赖(跳过脚本)..." pnpm install --ignore-scripts # 2. 批准白名单中的包 echo "✅ 批准必要的构建脚本..." APPROVAL_LIST=( "esbuild" "@esbuild/darwin-x64" "@esbuild/linux-x64" "@esbuild/win32-x64" ) for package in "${APPROVAL_LIST[@]}"; do echo "处理: $package" if pnpm list "$package" 2>/dev/null | grep -q "$package"; then echo "批准: $package" pnpm approve-builds --package "$package" --yes || true else echo "跳过: $package (未安装)" fi done # 3. 运行批准的构建脚本 echo "🔄 运行构建脚本..." pnpm rebuild echo "🎉 安装完成!" echo "" echo "已批准的包:" printf '%s\n' "${APPROVAL_LIST[@]}"

七、总结

7.1 快速解决方案

bash

# 最简单的方法(适合大多数 Vue3 项目) pnpm install --ignore-scripts=false # 或 pnpm config set ignore-scripts false pnpm install pnpm config set ignore-scripts true # 恢复安全设置

7.2 生产环境推荐

bash

# 1. 创建 .npmrc 文件 echo "ignore-scripts=false" >> .npmrc # 2. 使用 Docker 或 CI 脚本控制 # 3. 在安全的环境中构建

7.3 团队项目标准配置

创建项目初始化脚本:

bash

#!/bin/bash # init-project.sh echo "初始化 Vue3 + pnpm 项目..." # 创建必要的配置文件 cat > .npmrc << EOF # pnpm 配置 shamefully-hoist=true public-hoist-pattern[]=*esbuild* public-hoist-pattern[]=*vite* ignore-scripts=false strict-peer-dependencies=false EOF # 安装依赖 pnpm install echo "项目初始化完成!" echo "运行: pnpm run dev"

通过以上方法,您可以安全地解决 pnpm 的构建脚本阻止问题,同时保持项目的安全性。对于 Vue3 项目,主要需要关注esbuild相关包的构建脚本批准。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!