NodeJS必备,聊聊NPM镜像那些险象环生的坑(从头至尾全程小干货)

做者:JowayYoung
仓库:GithubCodePen
博客:掘金思否知乎简书头条CSDN
公众号:IQ前端
联系我:关注公众号后有个人微信
特别声明:原创不易,未经受权不得对此文章进行转载或抄袭,不然按侵权处理,如需转载或开通公众号白名单可联系我,但愿各位尊重原创的知识产权前端

前言

因为国内网络环境的缘由,在执行npm i安装项目依赖过程当中,确定会赶上安装过慢安装失败的状况。有经验的同窗一般会在安装完Node时顺便把NPM镜像设置成国内的淘宝镜像。node

npm config set registry https://registry.npm.taobao.org/
复制代码

这样就能爽歪歪应付大部分npm i的安装状况了。固然,这只是解决了大部分的安装过慢安装失败的状况,随着项目的深刻开发,确定还会赶上一些比较奇葩的状况,这也是笔者为何要写本文的缘由。python

管理镜像

你还可能会赶上这种状况,开发项目时使用淘宝镜像,可是发布NPM第三方模块时就必须使用原镜像了。在着手解决那些奇葩状况前,先推荐你们使用一个NPM镜像管理工具git

  • 原镜像https://registry.npmjs.org/
  • 淘宝镜像https://registry.npm.taobao.org/

主角就是nrm,它是一个可随时随地自由切换NPM镜像的管理工具。有了它,上面所说的什么时候使用什么镜像的问题就迎刃而解了。下面对其进行安装并简单讲解如何使用。github

安装sql

npm i -g nrm
复制代码

查看镜像chrome

nrm ls
复制代码

增长镜像npm

nrm add <name> <url>
复制代码

移除镜像json

nrm del <name>
复制代码

测试镜像segmentfault

nrm test <name>
复制代码

使用镜像

nrm use <name>
复制代码

查看当前镜像

nrm current
复制代码

熟悉命令后一波操做以下,原镜像淘宝镜像之间随意切换。固然,若是你记性好也不须要用这个工具了,哈哈。

nrm操做

遇坑填坑

有了nrm切换到淘宝镜像上,安装速度会明显加快,可是赶上安装的模块依赖了C++模块那就坑爹了。在安装过程当中会隐式安装node-gypnode-gyp可编译这些依赖C++模块的模块。

那么问题来了,node-gyp在首次编译时会依赖Node源码,因此又悄悄去下载Node。虽然在前面已设置了淘宝镜像,可是在这里一点卵用都没有。这样又由于国内网络环境的缘由,再次赶上安装过慢安装失败的状况。

还好npm config提供了一个参数disturl,它可设置Node镜像地址,固然仍是将其指向国内的淘宝镜像。这样又能爽歪歪安装这些依赖C++模块的模块了。

npm config set disturl https://npm.taobao.org/mirrors/node/
复制代码

问题一步一步解决,接下来又出现另外一个问题。日常你们都会使用node-sass做为项目开发依赖,可是node-sass的安装一直都是一个使人头疼的问题。

安装node-sass时,在install阶段会从Github上下载一个叫binding.node的文件,而GitHub Releases里的文件都托管在s3.amazonaws.com上,这个网址被Q了,因此又安装不了。

然而办法总比困难多,从node-sass的官方文档中可找到一个叫sass_binary_site的参数,它可设置Sass镜像地址,毫无疑问仍是将其指向国内的淘宝镜像。这样又能爽歪歪安装node-sass了。

npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/
复制代码

其实还有好几个相似的模块,为了方便,笔者仍是把它们源码里的镜像参数和淘宝镜像里对应的镜像地址扒出来,统一设置方便安装。如下是笔者经常使用的几个模块镜像地址配置,请收下!

分别是:SassSharpElectronPuppeteerPhantomSentrySqlitePython

镜像地址配置

npm config set <name> <url>,赶忙一键复制,永久使用。特别注意,别漏了最后面的/

npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/
npm config set sharp_dist_base_url https://npm.taobao.org/mirrors/sharp-libvips/
npm config set electron_mirror https://npm.taobao.org/mirrors/electron/
npm config set puppeteer_download_host https://npm.taobao.org/mirrors/
npm config set phantomjs_cdnurl https://npm.taobao.org/mirrors/phantomjs/
npm config set sentrycli_cdnurl https://npm.taobao.org/mirrors/sentry-cli/
npm config set sqlite3_binary_site https://npm.taobao.org/mirrors/sqlite3/
npm config set python_mirror https://npm.taobao.org/mirrors/python/
复制代码

有了这波操做,再执行npm i安装以上模块时就能享受国内的速度了。若是有条件,建议把这些镜像文件搬到本身或公司的服务器上,将镜像地址指向本身的服务器便可。在公司内网搭建一个这样的镜像服务器,一直安装一直爽,目前笔者所在的团队就是如此处理。

npm config set electron_mirror https://xyz/mirrors/electron/
复制代码

源码分析

以常常卡住的node-sass为例,下面是坑爹货node-sass/lib/extensions.js源码部分,可看出它会默认走GitHub Releases的托管地址,上面也分析过缘由,在这里就不重复了。

function getBinaryUrl() {
  const site = getArgument("--sass-binary-site")
    || process.env.SASS_BINARY_SITE
    || process.env.npm_config_sass_binary_site
    || (pkg.nodeSassConfig && pkg.nodeSassConfig.binarySite)
    || "https://github.com/sass/node-sass/releases/download";
  const result = [site, "v" + pkg.version, getBinaryName()].join("/");
  return result;
}
复制代码

而其余模块也有相似的代码,例如puppeteer这个安装Chronium源码部分,有兴趣的同窗都去扒一下源码,一模一样。

async function download() {
  await compileTypeScriptIfRequired();
  const downloadHost =
    process.env.PUPPETEER_DOWNLOAD_HOST
    || process.env.npm_config_puppeteer_download_host
    || process.env.npm_package_config_puppeteer_download_host;
  const puppeteer = require("./index");
  const product =
    process.env.PUPPETEER_PRODUCT
    || process.env.npm_config_puppeteer_product
    || process.env.npm_package_config_puppeteer_product
    || "chrome";
  const browserFetcher = puppeteer.createBrowserFetcher({
    product,
    host: downloadHost,
  });
  const revision = await getRevision();
  await fetchBinary(revision);
  // 还有不少
}
复制代码

坑货小结

因为node-sass是你们常用的项目开发依赖,也是安装时间较长和最多见到报错的模块,在这里笔者就花点篇章分析和解决下可能会遇到的问题。

node-sass安装失败的缘由其实并不止上面提到的状况,咱们可从安装过程当中分析并获取突破口来解决问题。根据npm i node-sass的输出信息来分析,可获得下面的过程。

  • 检测项目node_modulesnode-sass是否存在且当前安装版本是否一致
    • Yes:跳过,完成安装过程
    • No:进入下一步
  • NPM上下载node-sass
  • 检测全局缓存项目缓存中是否存在binding.node
    • Yes:跳过,完成安装过程
    • No:进入下一步
  • Github Releases上下载binding.node并将其缓存到全局
    • Success:将版本信息写入package-lock.json
    • Error:进入下一步
  • 尝试本地编译出binding.node
    • Success:将版本信息写入package-lock.json
    • Error:输出错误信息

不难看出,node-sass依赖了一个二进制文件binding.node,不只须要从NPM上下载本体还须要从Github Releases上下载binding.node


从实际状况来看,node-sass出现安装过慢安装失败的状况可能有如下几种:

NPM镜像托管在国外服务器

上面有提到,在这里再也不叙述,解决办法以下。

nrm use taobao
复制代码

安装过程当中悄悄下载node-gyp

上面有提到,在这里再也不叙述,解决办法以下。

npm config set disturl https://npm.taobao.org/mirrors/node/
复制代码

binding.node文件托管在国外服务器

上面有提到,在这里再也不叙述,解决办法以下。

npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/
复制代码

Node版本与node-sass版本不兼容

node-sass版本兼容性好差,必须与Node版本对应使用才行,详情请参考node-sass-version-association,复用官方文档的版本对照表,以下。

NodeJS Minimum node-sass version Node Module
Node 14 4.14+ 83
Node 13 4.13+ 79
Node 12 4.12+ 72
Node 11 4.10+ 67
Node 10 4.9+ 64
Node 8 4.5.3+ 57

执行npm i安装依赖前请确保当前的Node版本和node-sass版本已兼容。

全局缓存中的binding.node版本与Node版本不兼容

假如本地使用nvmn进行Node版本管理,而且已切换了Node版本,在安装过程当中可能会出现Windows/OS X/Linux 64-bit with Node.js 12.x这样的提示,这种状况也是笔者常常赶上的状况(笔者电脑里安装了30多个Node版本而且常常来回切换😂)。

这是由于node-sass版本和Node版本是关联的(看上面的表格),修改Node版本后在全局缓存中匹配不到对应的binding.node文件而致使安装失败。根据错误提示,清理NPM缓存且从新安装便可,解决办法以下。

npm cache clean -f

npm rebuild node-sass
复制代码

因此没什么事就别来回切换Node版本了,像笔者装这么多Node版本也是逼不得已,老项目太多了😂。

安装失败后从新安装

有可能无权限删除已安装的内容,致使从新安装时可能会产生某些问题,建议将node_modules所有删除并从新安装。

在Mac系统和Linux系统上删除node_modules比较快,可是在Windows系统上删除node_modules就比较慢了,推荐你们使用rimraf删除node_modules,一个Node版的rm -rf工具。

npm i -g rimraf
复制代码

在项目的package.json中加入npm scriptsrimraf常驻。三大操做系统通用,很是推荐使用。

{
  "scripts": {
    "reinstall": "rimraf node_modules && npm i"
  }
}
复制代码

一有什么安装失败从新安装之类的操做,先执行npm run remove删除node_modulesnpm i

npm run reinstall
复制代码

终极总结

若是看得有点乱,那下面直接贴代码操做顺序,建议前端小白在安装完Node后立马处理这些NPM镜像问题,防止后续产生没必要要的麻烦(解决这些问题是须要花费时间的😂)。

# 查看Node版本和NPM版本确认已安装Node环境
node -v
npm -v

# 安装nrm并设置NPM的淘宝镜像
npm i -g nrm
nrm use taobao

# 设置依赖安装过程当中内部模块下载Node的淘宝镜像
npm config set disturl https://npm.taobao.org/mirrors/node/

# 设置经常使用模块的淘宝镜像
npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/
npm config set sharp_dist_base_url https://npm.taobao.org/mirrors/sharp-libvips/
npm config set electron_mirror https://npm.taobao.org/mirrors/electron/
npm config set puppeteer_download_host https://npm.taobao.org/mirrors/
npm config set phantomjs_cdnurl https://npm.taobao.org/mirrors/phantomjs/
npm config set sentrycli_cdnurl https://npm.taobao.org/mirrors/sentry-cli/
npm config set sqlite3_binary_site https://npm.taobao.org/mirrors/sqlite3/
npm config set python_mirror https://npm.taobao.org/mirrors/python/
复制代码

针对node-sass的状况:

# 安装rimraf并设置package.json
npm i -g rimraf

# 安装前请确保当前的Node版本和node-sass版本已兼容

# 安装失败
npm cache clean -f
npm rebuild node-sass 或 npm run reinstall
复制代码

package.json中加入npm scripts

{
  "scripts": {
    "reinstall": "rimraf node_modules && npm i"
  }
}
复制代码

总结

NPM镜像问题的坑确实不少,归根到底仍是网络环境致使的。固然这些问题也阻碍不了乐于探索的咱们,办法总比困难多,坚持下去始终能找到解决方式。

笔者总结出一个解决这种NPM镜像问题的好方法,遇到一些上面没有提到的模块,可尝试经过如下步骤去解决问题。

  • 执行npm i前设置淘宝镜像,保证安装项目依赖时都走国内网络
  • 安装不成功时,确定是在安装过程当中该模块内部又去下载了其余国外服务器的文件
  • 在Github上克隆一份该模块的源码进行分析,搜索包含base、binary、cdn、config、dist、download、host、mirror、npm、site、url等这样的关键词(自行探索,一般mirror的匹配度最高)
  • 在搜查结果里查找形态像镜像地址的代码块,再分析该代码块的功能并提取最终的镜像地址,例如node-sasssass_binary_site
  • 去淘宝镜像官网、百度、谷歌等网站查找你须要的镜像地址,若是实在找不到就规范上网把国外服务器的镜像文件拉下来搬到本身或公司的服务器上
  • 设置模块依赖的镜像地址:npm config set <registry name> <taobao url / yourself url>
  • 从新执行npm i安装项目依赖,大功告成

若是以上内容帮不了你或在解决NPM镜像问题上还遇到其余坑,欢迎添加笔者微信一块儿交流。若有错误地方也欢迎指出,若有更好的解决方法也可提上建议。

另外笔者花了一些时间用Xmind整理了本文内容并生成一张知识点分布图,浓缩就是精华。因为图片太大没法上传就保存到公众号里,若有须要可关注IQ前端,扫描文章底部二维码,后台回复NPM镜像获取该图片,但愿能帮助到你。

结语

❤️关注+点赞+收藏+评论+转发❤️,原创不易,鼓励笔者创做更好的文章

关注公众号IQ前端,一个专一于CSS/JS开发技巧的前端公众号,更多前端小干货等着你喔

  • 关注后回复关键词免费领取视频教程
  • 关注后添加我微信拉你进技术交流群
  • 欢迎关注IQ前端,更多CSS/JS开发技巧只在公众号推送

相关文章
相关标签/搜索