踩坑记录:Mac M系列芯片下 pnpm dlx 触发的 esbuild 架构不匹配错误
背景
在日常开发中,克隆一个前端项目后,我们习惯性地执行 pnpm install 和 pnpm dev。但最近在搭载 Apple Silicon (M系列芯片) 的 Mac 上,项目启动时却抛出了一个极其刺眼的致命错误,甚至重新 git clone 项目也无法解决。
错误现象
执行命令后,终端抛出如下错误堆栈,直接导致进程退出 (exit code 1):
node:internal/modules/run_main:123
triggerUncaughtException(
^
Error:
You installed esbuild for another platform than the one you're currently using.
This won't work because esbuild is written with native code and needs to
install a platform-specific binary executable.
Specifically the "@esbuild/darwin-x64" package is present but this platform
needs the "@esbuild/darwin-arm64" package instead. People often get into this
situation by installing esbuild with npm running inside of Rosetta 2 and then
trying to use it with node running outside of Rosetta 2, or vice versa (Rosetta
2 is Apple's on-the-fly x86_64-to-arm64 translation service).
...
at generateBinPath (/Users/xxx/Library/Caches/pnpm/dlx/fa19b49eb7fa...)
at esbuildCommandAndArgs (/Users/xxx/Library/Caches/pnpm/dlx/fa19b...)
...
问题分析
错误信息其实已经说得很清楚了:架构不匹配 (Architecture Mismatch)。
esbuild 是一个使用 Go 语言编写的高性能构建工具,它在安装时会根据当前的操作系统和 CPU 架构下载对应的底层二进制文件。
在我们的场景中:
- 期望环境:Mac M系列芯片,原生架构是
arm64(darwin-arm64)。 - 实际加载的包:系统却发现本地存在的是为 Intel 芯片编译的包
darwin-x64。
为什么重新 clone 项目也没用?
这就是这个 Bug 最搞人心态的地方。如果你仔细观察报错堆栈,会发现错误并不是从项目本地的 node_modules 抛出的,而是来自:
/Users/xxx/Library/Caches/pnpm/dlx/...
这说明问题出在执行 pnpm dlx 命令时。pnpm dlx 类似于 npx,用于临时下载并执行一个包。pnpm 把之前(可能是在旧的 Intel Mac 上,或者是误用 Rosetta 终端时)下载的 darwin-x64 版本的包缓存在了全局的 dlx 目录中。
当你再次运行项目时,哪怕项目是全新 clone 的,pnpm dlx 依然会去读取这个全局的、架构错误的缓存,从而导致崩溃。
解决方案
明确了是全局缓存作祟,解决起来就非常简单粗暴了:进行深度清理。
第一步:核实 Node.js 架构
首先,必须确保你当前运行的 Node.js 本身是原生的 arm64 版本,而不是通过 Rosetta 2 翻译运行的 Intel 版本。
在终端输入:
node -p "process.arch"
- 如果输出是
arm64,说明环境正确,请进行下一步。 - 如果输出是
x64,说明你的 Node.js 版本不对。你需要卸载当前的 Node.js,并重新安装原生版本(例如使用nvm install <version>)。同时检查你的终端软件(Terminal/iTerm2)是否在“显示简介”中勾选了“使用 Rosetta 打开”,如果有,请取消勾选。
第二步:彻底清空 pnpm 的全局 DLX 缓存
既然缓存污染了,我们就手动将其根除。在终端执行以下命令:
# 强制删除 pnpm 的全局 dlx 缓存目录(将 /Users/xxx 替换为你报错信息中的实际路径,通常是 ~/.local/share/pnpm 或 ~/Library/Caches/pnpm)
rm -rf ~/Library/Caches/pnpm/dlx
# 清理 pnpm 的全局 store 缓存
pnpm store prune
第三步:重新安装依赖
回到你的项目根目录,为了保险起见,清空本地的 node_modules,然后重新安装:
# 删除本地 node_modules
rm -rf node_modules
# 重新安装依赖,此时 pnpm dlx 会重新拉取正确的 arm64 版本
pnpm install
# 启动项目
pnpm dev
总结
当我们在 Mac M 系列芯片上遇到类似 @esbuild/darwin-x64 与 @esbuild/darwin-arm64 的冲突,且重装项目无效时,一定要优先排查全局缓存(如 pnpm dlx 缓存目录)以及 Node.js 自身的运行架构。暴力清理特定的全局缓存目录,往往是解决此类“幽灵报错”的最快途径。