Node-sass 安装错误解决方案
解决 node-sass 安装时的常见报错问题
问题背景
在前端开发中,我们经常需要维护一些历史悠久的项目。由于定制项目的特殊性,经常会有五六年前的老项目突然需要做变更或优化需求。当你满怀期待地准备进行项目安装时,往往会遭遇各种令人头疼的错误。
常见报错场景
场景一:Python 2 环境缺失 🐍
bash
2094 verbose argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Users\\Gary.Lu\\AppData\\Roaming\\npm\\node_modules\\npm\\bin\\npm-cli.js" "install"
2095 verbose node v16.13.1
2096 verbose npm v8.3.0
2097 error code 1
2098 error path C:\Users\Gary.Lu\Documents\ITTS Projects\AXMES\MAIN\ITTS-MES\WEB\node_modules\node-sass
2099 error command failed
2100 error command C:\WINDOWS\system32\cmd.exe /d /s /c node scripts/build.js
2101 error Building: C:\Program Files\nodejs\node.exe C:\Users\Gary.Lu\Documents\MyWeb\node_modules\node-gyp\bin\node-gyp.js rebuild --verbose --libsass_ext= --libsass_cflags= --libsass_ldflags= --libsass_library=
2102 error gyp info it worked if it ends with ok
2102 error gyp verb cli [
2102 error gyp verb cli 'C:\\Program Files\\nodejs\\node.exe',
2102 error gyp verb cli 'C:\\Users\\Gary.Lu\\Documents\\MyWeb\\node_modules\\node-gyp\\bin\\node-gyp.js',
2102 error gyp verb cli 'rebuild',
2102 error gyp verb cli '--verbose',
2102 error gyp verb cli '--libsass_ext=',
2102 error gyp verb cli '--libsass_cflags=',
2102 error gyp verb cli '--libsass_ldflags=',
2102 error gyp verb cli '--libsass_library='
2102 error gyp verb cli ]
2102 error gyp info using node-gyp@3.8.0
2102 error gyp info using node@16.13.1 | win32 | x64
2102 error gyp verb command rebuild []
2102 error gyp verb command clean []
2102 error gyp verb clean removing "build" directory
2102 error gyp verb command configure []
2102 error gyp verb check python checking for Python executable "python2" in the PATH
2102 error gyp verb `which` failed Error: not found: python2
2102 error gyp verb `which` failed at getNotFoundError (C:\Users\Gary.Lu\Documents\MyWeb\node_modules\which\which.js:13:12)
2102 error gyp verb `which` failed at F (C:\Users\Gary.Lu\Documents\MyWeb\node_modules\which\which.js:68:19)
2102 error gyp verb `which` failed at E (C:\Users\Gary.Lu\Documents\MyWeb\node_modules\which\which.js:80:29)
2102 error gyp verb `which` failed at C:\Users\Gary.Lu\Documents\MyWeb\node_modules\which\which.js:89:16
2102 error gyp verb `which` failed at C:\Users\Gary.Lu\Documents\MyWeb\node_modules\isexe\index.js:42:5
2102 error gyp verb `which` failed at C:\Users\Gary.Lu\Documents\MyWeb\node_modules\isexe\windows.js:36:5
2102 error gyp verb `which` failed at FSReqCallback.oncomplete (node:fs:198:21)
2102 error gyp verb `which` failed python2 Error: not found: python2
2102 error gyp verb `which` failed at getNotFoundError (C:\Users\Gary.Lu\Documents\MyWeb\node_modules\which\which.js:13:12)
2102 error gyp verb `which` failed at F (C:\Users\Gary.Lu\Documents\MyWeb\node_modules\which\which.js:68:19)
2102 error gyp verb `which` failed at E (C:\Users\Gary.Lu\Documents\MyWeb\node_modules\which\which.js:80:29)
2102 error gyp verb `which` failed at C:\Users\Gary.Lu\Documents\MyWeb\node_modules\which\which.js:89:16
2102 error gyp verb `which` failed at C:\Users\Gary.Lu\Documents\MyWeb\node_modules\isexe\index.js:42:5
2102 error gyp verb `which` failed at C:\Users\Gary.Lu\Documents\MyWeb\node_modules\isexe\windows.js:36:5
2102 error gyp verb `which` failed at FSReqCallback.oncomplete (node:fs:198:21) {
2102 error gyp verb `which` failed code: 'ENOENT'
2102 error gyp verb `which` failed }
2102 error gyp verb check python checking for Python executable "python" in the PATH
2102 error gyp verb `which` succeeded python C:\Python310\python.EXE
2102 error gyp ERR! configure error
2102 error gyp ERR! stack Error: Command failed: C:\Python310\python.EXE -c import sys; print "%s.%s.%s" % sys.version_info[:3];
2102 error gyp ERR! stack File "<string>", line 1
2102 error gyp ERR! stack import sys; print "%s.%s.%s" % sys.version_info[:3];
2102 error gyp ERR! stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2102 error gyp ERR! stack SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?
2102 error gyp ERR! stack
2102 error gyp ERR! stack at ChildProcess.exithandler (node:child_process:397:12)
2102 error gyp ERR! stack at ChildProcess.emit (node:events:390:28)
2102 error gyp ERR! stack at maybeClose (node:internal/child_process:1064:16)
2102 error gyp ERR! stack at Process.ChildProcess._handle.onexit (node:internal/child_process:301:5)
2102 error gyp ERR! System Windows_NT 10.0.19044
2102 error gyp ERR! command "C:\\Program Files\\nodejs\\node.exe" "C:\\Users\\Gary.Lu\\Documents\\MyWeb\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library="
2102 error gyp ERR! cwd C:\Users\Gary.Lu\Documents\MyWeb\node_modules\node-sass
2102 error gyp ERR! node -v v16.13.1
2102 error gyp ERR! node-gyp -v v3.8.0
2102 error gyp ERR! not ok
2102 error Build failed with error code: 1
2103 verbose exit 1
2104 timing npm Completed in 53164ms
2105 verbose unfinished npm timer reify 1640746055969
2106 verbose unfinished npm timer reify:build 1640746094013
2107 verbose unfinished npm timer build 1640746094014
2108 verbose unfinished npm timer build:deps 1640746094014
2109 verbose unfinished npm timer build:run:postinstall 1640746099176
2110 verbose unfinished npm timer build:run:postinstall:node_modules/node-sass 1640746099176
2111 verbose code 1
2112 error A complete log of this run can be found in:
2112 error C:\Users\Gary.Lu\AppData\Local\npm-cache\_logs\2021-12-29T02_47_34_408Z-debug-0.log
场景二:Node 版本兼容性问题 ⚠️
bash
gyp ERR! build error
gyp ERR! stack Error: `C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe` failed with exit code: 1
gyp ERR! stack at ChildProcess.onExit (C:\Users\Max-T\Documents\Sources\StaffMangerV2\black-dashboard-pro-react-v1.0.0\node_modules\node-gyp\lib\build.js:262:23)
gyp ERR! stack at ChildProcess.emit (events.js:210:5)
gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:272:12)
gyp ERR! System Windows_NT 10.0.18362
gyp ERR! command "C:\\Program Files\\nodejs\\node.exe" "C:\\Users\\Max-T\\Documents\\Sources\\StaffMangerV2\\black-dashboard-pro-react-v1.0.0\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library="
gyp ERR! cwd C:\Users\Max-T\Documents\Sources\StaffMangerV2\black-dashboard-pro-react-v1.0.0\node_modules\node-sass
gyp ERR! node -v v12.13.0
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok
Build failed with error code: 1
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.4 (node_modules\react-scripts\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.4: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! node-sass@4.11.0 postinstall: `node scripts/build.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the node-sass@4.11.0 postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Max-T\AppData\Roaming\npm-cache\_logs\2019-10-30T10_05_01_386Z-debug.log
传统解决方案的困境 😰
更加让人绝望的是,当你按照网上的各种教程尝试解决:
- 🐍 安装 Python 2
- 🔄 切换 Node 环境版本
- 🌐 搭梯子、修改编辑器或命令行代理
- 📦 修改镜像源、二进制包地址
- 🐳 甚至使用 Docker DevContainer
bash
$ npm set registry https://registry.npmmirror.com # 注册模块镜像
$ npm set disturl https://npmmirror.com/dist/node # node-gyp 编译依赖的 node 源码镜像
// 以下根据自己需要选择添加
$ npm config set proxy http://example.com:8080 # 设置代理
$ npm set sass_binary_site https://npmmirror.com/mirrors/node-sass # node-sass 二进制包镜像
$ npm i -D node-sass@3.13.1 --sass_binary_path=C:\Users\<username>\Downloads\win32-x64-57_binding.node // 下载相关的sass_binary 404,强行指定path
$ npm set chromedriver_cdnurl https://npmmirror.com/mirrors/chromedriver # chromedriver 二进制包镜像
$ npm set operadriver_cdnurl https://npmmirror.com/mirrors/operadriver # operadriver 二进制包镜像
$ npm set phantomjs_cdnurl https://npmmirror.com/mirrors/phantomjs # phantomjs 二进制包镜像
$ npm set fse_binary_host_mirror https://npmmirror.com/mirrors/fsevents # fsevents 二进制包
$ npm set electron_mirror https://npmmirror.com/mirrors/electron/ # electron 二进制包镜像
你会发现项目依赖依然无法正常安装!仅仅是一个简单的文字修改,却已经耗费了两个小时。此时的你可能已经开始汗流浃背了... 😅
终极解决方案 ✨
其实,解决这个问题的方法出奇地简单!我们只需要在 package.json
中添加相应的字段,将 node-sass
替换为现代化的 sass
:
Yarn 解决方案
使用 resolutions
字段:
json
{
"resolutions": {
"node-sass": "npm:sass@^1.32.0"
}
}
pnpm 解决方案
使用 overrides
字段:
json
{
"pnpm": {
"overrides": {
"node-sass": "npm:sass@^1.32.0"
}
}
}
然后执行安装命令:
bash
npm install
# 或者
yarn install
# 或者
pnpm install
搞定!🎉
原理解析 🔍
为什么 node-sass 这么难装?
- 原生依赖:
node-sass
依赖于 LibSass,需要在安装时进行本地编译 - Python 依赖:编译过程需要 Python 2.x 环境(现在已经停止维护)
- Node 版本敏感:不同版本的 Node.js 需要对应的二进制文件
- 网络问题:二进制文件下载经常因为网络问题失败
为什么 sass 是更好的选择?
- 纯 JavaScript 实现:
sass
(Dart Sass)是纯 JS 实现,无需编译 - 官方推荐:Sass 官方推荐使用 Dart Sass
- 更好的兼容性:支持最新的 Sass 语法特性
- 更快的性能:在大多数情况下性能更优
其他解决方案 🛠️
方案一:直接替换依赖
如果你有项目的修改权限,可以直接将 node-sass
替换为 sass
:
bash
# 卸载 node-sass
npm uninstall node-sass
# 安装 sass
npm install sass --save-dev
注意
这种方法在某些情况下可能不生效,特别是当 node-sass
是框架(如 Taro)的间接依赖时,你无法直接修改框架内部的依赖关系。
方案二:使用 .npmrc 配置
在项目根目录创建 .npmrc
文件:
ini
# 使用国内镜像
registry=https://registry.npmmirror.com/
sass_binary_site=https://npmmirror.com/mirrors/node-sass/
方案三:锁定版本
如果必须使用 node-sass
,可以锁定一个稳定版本:
json
{
"devDependencies": {
"node-sass": "4.14.1"
}
}
总结 📝
node-sass
的安装问题一直是前端开发者的痛点,但通过使用 resolutions
字段将其替换为现代化的 sass
,我们可以轻松解决这个问题。这不仅解决了安装难题,还能享受到更好的性能和更完整的功能支持。
记住:拥抱新技术,告别历史包袱! 🚀