从安装过程详解node-sass

我们在安装依赖的时候,经常会附带安装node-sass,而node-sass会经常安装报错,一般都是gyp的error


image.png

我们来分析下安装过程

安装过程

  1. npm下载到node-sass这个包
  2. 触发了node-sass这个包的install的钩子,或者说生命周期,然后执行了install.js


    image.png
  3. install.js里会尝试去手动下载它的一个c++模块,也就是一个.node文件,他会先尝试去环境里获取这个c++模块的镜像地址,如果你配置了镜像地址的话,优先从你的镜像地址下载


    image.png
  4. 而这个sass.getBinaryUrl方法里会尝试用各种手段获取镜像
    比如
  • --sass-binary-site就是命令行里的参数
  • process.env.SASS_BINARY_SITE 就是环境变量里的
  • npm_config_sass_binary_site,就是.npmrc文件里的sass_binary_site,.npmrc里面的变量会自动被注入到临时环境变量里,转换成以npm_config带头的变量名
  • pkg.nodeSassConfig或者pkg.nodeSassConfig.binarySite 则是写在package.json中的镜像地址
    image.png

所以我们在网上经常能搜到的解决方案就是安装报错时,去.npmrc文件中配置镜像,使得该binary可以下载到,一般是这么配置

sass_binary_site=https://www.npmmirror.com/mirrors/node-sass

  1. 如果这些都没有配置的话,就有一个默认的github的下载地址 https://github.com/sass/node-sass/releases/download,这个地址现在点进去看是不存在的,因为路径还没拼完

  2. 从上方的图里大概可以猜到,完整地址应该是
    https://github.com/sass/node-sass/releases/download/v版本号/binary的名字
    现在我们缺少版本号和bindary名字

  3. 版本号很容易得知,就是安装的node-sass的版本号

  4. 后面的binaryName,直接看下图框起来的部分即可,因为正常情况下图里其他的if条件都不会满足,正常情况下不会特地去配这些变量

    image.png

  5. binaryName我们可以根据图里的规则自己拼下,直接在自己电脑上获取下, 输入node -p [process.platform,process.arch,process.versions.modules].join('-')"

    image.png

  6. 所以完整下载地址,应该是https://github.com/sass/node-sass/releases/download/v4.14.1/win32-x64-108_binding.node,也就是说node-sass在安装过程中会拼出这个地址来,然后从这个地址去下载binary

  7. 但是会发现,这个地址点进去404了,不存在该下载地址

  8. 因为node-sass,在4.14.1版本,没有win32-x64-108这个型号的.node文件,我们去它github的release里找到这个4.14.1的版本号,再往下找assets,会发现,最多就到83,没有到108的


    image.png
  9. 所以即便你配置了阿里云镜像,也没用,因为这个版本号对应的.node文件就那么少

  1. 而下载不到.node文件时,不会报错,但是会触发另一个hook,postinstall,这是完成安装后触发的


    image.png

    在这个build.js里他会去各种判断binary是否存在,然后尝试编译一行sass语法,如果有任何报错,都会尝试重新本地build出这个.node文件

image.png
  1. 而这个build函数里,我们会发现,他需要用node-gyp编译,而node-gyp需要python环境,没安装的时候就报错了


    image.png

    image.png
  1. 回到上面的话题,再往上翻,我们会发现,只有v8.0.0版本的node-sass,才有到108的binary


    image.png
  2. 但是v8.0.0版本的node-sass,未必能和项目当前的sass-loader能兼容,即便sass-loader能升上去,但项目里用的是webpack4,webpack4未必能和这么高版本的sass-loader兼容

  3. 所以我们需要把后面的数值降下去,把win32-x64-108后面的-108给降下去,这个和当前的node版本有关,我现在用的是node18,所以是win32-x64-108

  4. 使用nvm切换到node16版本,切换后我们再试下刚才的命令


    image.png
  5. 可以看到已经降到93了,93的最低要求版本是v6.0.0


    image.png
  6. 然后继续安装依赖,发现还是报错,这.npmrc文件配置了镜像,版本也对了,手动去下载这个.node文件也能下载到,为什么还报错??

  7. 于是手动把node-sass的git仓库clone下来,加了.npmrc,然后执行npm i,发现是地址不对,然后在关键位置打了log后发现


    image.png
  8. .npmrc里明明配置的是阿里云镜像,为什么这边获取到的是淘宝镜像??


    image.png
  1. 经过排查发现,是因为我按照node-sass的官方的readme文件,执行了npm install -g mirror-config-china配置镜像地址
    image.png

后面的--registry配置的是这个mirror-config-china的下载地址,而mirror-config-china下载到了后,都不用手动执行,直接自动往用户目录下的全局.npmrc文件里写入一堆的淘宝镜像地址,这是写死的

  1. 淘宝镜像地址2024年证书已经过期了,这个包写入的全是错的,所以把用户目录下的.npmrc文件清空就行了

  2. 所以可以分析出,npm install过程中,会先读取项目目录下.npmrc的配置,并转换成npm_config带头的变量,临时写入到shell的环境变量中,然后再读取用户目录下的.npmrc文件,再转临时变量写入shell,此时如果有两个相同的临时变量名,项目里.npmrc里的就会被覆盖

  3. 清空该文件内容


    image.png
  4. 然后安装成功,安装成功是clone下来的node-sass的git仓库安装依赖成功了,并且postinstall也成功了,
    此时我们清掉缓存重新回到项目里安装依赖,.node缓存有两个位置,一个当前项目里的vender文件夹里,还有一个是全局的


    image.png
  5. 清掉这两个缓存后再回到项目里安装,发现又报了个错,此时怀疑不是node-sass的问题,因为单独把node-sass拎出来是可以的,而且报的错看着和node-sass没啥关系


    企业微信截图_17289748906132.png
9886 verbose stack Error: command failed
9886 verbose stack     at ChildProcess.<anonymous> (C:\Users\Administrator\AppData\Roaming\nvm\v16.18.1\node_modules\npm\node_modules\@npmcli\promise-spawn\lib\index.js:63:27)
9886 verbose stack     at ChildProcess.emit (node:events:513:28)
9886 verbose stack     at maybeClose (node:internal/child_process:1100:16)
9886 verbose stack     at Process.ChildProcess._handle.onexit (node:internal/child_process:304:5)
9887 verbose pkgid node-sass@6.0.1

报错后回到全局缓存目录查看,发现node-sass的binary是已经下载到了的,因为之前确定把这些都清空了


image.png
  1. 改成pnpm安装后成功,而npm安装就是失败

  2. 再仔细看报错位置,是执行node-sass在执行postinstall的时候,node build.js抛出的错,所以仔细观察build.js这个文件

  3. .node文件确定是已经下载到了的,那么也就是说可能是在这段代码里执行报错了


    image.png
  4. 但是再仔细想想也不对,如果执行报错,会走到下面的catch,起码会log输出Binary has a problem或者Building the binary locally这两句话来,可npm error里并没有这些log

  5. 所以只能是前面的代码执行有问题


    image.png
  6. 先看第一行if里的options.force,然后找到options.force 是怎么来的,这下破案了


    image.png
  7. 也就是说,.npmrc里面如果有force=true,或者install 的命令后面跟着--force或者-f的话,直接会先用node-gyp强行build,而我这个老项目里,因为各种依赖不对等导致安装报错,然后用了 npm install --force,想忽略依赖不对等问题直接安装,然后这个--force刚好被node-sass解析到,尝试强行build一个.node文件,因为没有配置环境,就失败了
    而pnpm安装时没有报错,所以没有加--force,单独拉node-sass仓库install时也没有加--force,所以这两个情况下反而可以成功

  8. 知道是--force命令带来的问题就好办了,把npm install --force 换成 npm install --legacy-peer-deps 即可

总结

  1. node-sass下载不到时,.npmrc文件里面可以配置对应的.node文件的地址,但是要注意node版本和对应的node-sass版本必须匹配,否则即便配置了国内镜像地址也下载不到

  2. 千万别看node-sass的readme文件去执行npm install -g mirror-config-china,这命令会往全局的.npmrc里写入sass_binary_site为淘宝镜像地址,这个配置会在运行时覆盖项目里的.npmrc,而淘宝镜像的https证书过期了

  3. 有node-sass依赖的项目,install时别加--force,否则会强行本地编译一个.node文件,也会报错

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354

推荐阅读更多精彩内容