Skip to content

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 版本兼容性问题 ⚠️

lDOOM7GyxuQO

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 这么难装?

  1. 原生依赖node-sass 依赖于 LibSass,需要在安装时进行本地编译
  2. Python 依赖:编译过程需要 Python 2.x 环境(现在已经停止维护)
  3. Node 版本敏感:不同版本的 Node.js 需要对应的二进制文件
  4. 网络问题:二进制文件下载经常因为网络问题失败

为什么 sass 是更好的选择?

  1. 纯 JavaScript 实现sass(Dart Sass)是纯 JS 实现,无需编译
  2. 官方推荐:Sass 官方推荐使用 Dart Sass
  3. 更好的兼容性:支持最新的 Sass 语法特性
  4. 更快的性能:在大多数情况下性能更优

其他解决方案 🛠️

方案一:直接替换依赖

如果你有项目的修改权限,可以直接将 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,我们可以轻松解决这个问题。这不仅解决了安装难题,还能享受到更好的性能和更完整的功能支持。

记住:拥抱新技术,告别历史包袱! 🚀