node-sass 安装失败:not a mach-o file / distutils 报错怎么修
最近装一个老项目依赖,node-sass 又炸了。
看起来是两个报错:
not a mach-o file
还有一个:
ModuleNotFoundError: No module named 'distutils'
这两个错误连在一起,很容易把人绕晕。
说人话就是:
先下载到了一个坏的
binding.node文件,不能用;然后它想本地编译,结果你的 Python 太新,老的构建工具又跑不起来。
问题现象
node-sass 安装时会先下载一个预编译好的二进制文件。
这个文件一般叫:
binding.node
正常情况下,它应该是一个真正的 native binary。
但这次下载到的东西是坏的。可能是 npm 镜像、代理、缓存出了问题,把一个 404 页面或者错误响应当成了 binding.node 缓存下来。
于是 macOS 加载它的时候就会报:
not a mach-o file
意思是:
你让我加载一个 macOS 二进制文件,但这个文件根本不是二进制文件。
所以第一层问题是:下载到的 binding.node 是坏的。
真正原因
node-sass 的安装逻辑大概是这样:
先下载预编译 binary
↓
下载失败或文件坏了
↓
改成本地编译
↓
调用 node-gyp
↓
node-gyp 调 Python
↓
Python 3.12+ 没有 distutils
↓
安装失败
所以这不是一个单点问题,而是两个问题叠加:
binding.node下载坏了;- fallback 到本地编译时,Python 3.12+ 又不兼容老版本
node-gyp。
distutils 以前是 Python 里的一个构建相关模块。老版本 node-gyp 会依赖它。
但 Python 3.12 之后,distutils 没了,所以就报:
ModuleNotFoundError: No module named 'distutils'
怎么修
按优先级来,不要一上来乱改。
1. 先重新下载正确的 binary
先清缓存:
rm -rf node_modules
rm -f package-lock.json
npm cache clean --force
然后换一个可用的 node-sass binary 地址:
SASS_BINARY_SITE=https://npmmirror.com/mirrors/node-sass npm install
如果只是镜像缓存坏了,这一步通常就够了。
2. 如果还失败,就指定 Python 3.11
如果 binary 还是下不下来,node-sass 会尝试本地编译。
这时不要用 Python 3.12+,改用 Python 3.11。
先找到 Python 3.11 路径:
which python3.11
然后告诉 npm 使用它:
npm config set python /path/to/python3.11
例如 macOS Homebrew 可能是:
npm config set python /opt/homebrew/bin/python3.11
再重新安装:
rm -rf node_modules
npm install
这一步解决的是:本地编译时 Python 版本不兼容的问题。
3. 长期方案:迁移到 sass
如果这个项目还会继续维护,最好别继续跟 node-sass 纠缠。
直接迁移到 Dart Sass,也就是 npm 包里的 sass:
npm uninstall node-sass
npm install sass
如果项目里必须保留 node-sass 这个包名,也可以用 npm alias:
{
"node-sass": "npm:sass@^1.77.0"
}
不过更推荐直接改成:
{
"sass": "^1.77.0"
}
原因很简单:
sass不依赖 native binary,也就不会再被 Python、node-gyp、CPU 架构、npm mirror 这些东西卡住。
我的建议
短期修复:
rm -rf node_modules
rm -f package-lock.json
npm cache clean --force
SASS_BINARY_SITE=https://npmmirror.com/mirrors/node-sass npm install
如果还不行:
npm config set python /path/to/python3.11
npm install
长期修复:
npm uninstall node-sass
npm install sass
这次问题的核心其实就一句话:
not a mach-o file是 binary 坏了;No module named distutils是 fallback 编译时 Python 太新了。
所以别只盯着 Python,也别只盯着 npm。
真正的问题是:
坏的 node-sass binary + 老的 node-gyp 构建链 + Python 3.12 兼容性问题
能救急就先换 binary。
要长期稳定,就迁移到 sass。
Be the first to know when I post cool stuff
Subscribe to get my latest posts by email.
Thanks for signing up! Check your email to confirm your subscription.
Whoops, we weren't able to process your signup.