国内的前端开发者或多或少对cnpm有所了解,但是项目开发因人而异,很多时候不会或者不会用cnpm,无数的项目都是使用yarn或其他包管理器来安装依赖项。本文介绍了在这种情况下如何加快二进制文件的下载速度。在前段时间发布的GithubOctoverse2019报告中,JavaScript继续成为最受欢迎的编程语言。JavaScript生态的繁荣与Node.js的流行密不可分。说到JavaScript生态,就不得不提npm。Npm不仅是前端开发的首选包管理器,也是除Github之外最重要的代码共享渠道。Snyk的2019年开源安全年度报告指出,npm生态系统中的包数量远超其他包管理器。现阶段主流的前端开源项目在发布时都会使用npm的在线托管服务https://www.npmjs.com/。但是开发人员不仅可以使用npm作为包管理器。来自开源社区的Yarn和pnpm正在被越来越多的人使用。它们最显着的优势是加快依赖项的安装。对于中国开发者来说,阿里巴巴开源的cnpm也是一个重要的选择。关于CNPM的那些事儿自从以react和vue为主导的前端工程化开发在国内大规模流行以来,前端项目的依赖安装就成为了日常工作的重要内容。cnpm的出现解决了网络环境导致的安装速度慢的问题,受到了国内广大开发者的欢迎。cnpm早于yarn和pnpm,并使用npminstall模块执行安装。淘宝开发团队维护的npm仓库镜像会定时同步所有官方npm模块。cnpm默认会从淘宝镜像下载所有包,无需任何配置,从而达到国内加速的目的。具体使用请参考官方文档https://npm.taobao.org/。虽然cnpm现在的速度一如既往的快,但是和其他竞品相比,已经没有了刚诞生时的优势。另外,实际开发中莫名其妙的报错很难解决,还有其他各种因素。越来越多的团队正在切换回npm,或者切换到yarn或pnpm以获得更多功能。Yarn是来自Facebook团队的开源包管理器。它创建了一个更扁平的依赖树,只安装更改的模块,使用并行下载,并使用本地缓存来加速安装。作为一匹黑马,pnpm的口碑要好于yarn,但由于笔者没有使用经验,本文就不介绍如何使用了。我想肯定有一些读者要吐槽,为什么不用cnpm还要折腾呢?但对此没有具体的答案。每个球队、每个人都有自己的情况,没必要去批判。毕竟是发现问题,解决问题。接下来介绍如何使用最小配置让yarn也获得cnpm的国内加速能力。NPM和YARN使用镜像加速这部分已经不是什么新鲜事了,所有包管理器都可以设置仓库地址。具体细节建议阅读npm的官方文档。除了“大家熟知的命令行配置方式”之外,还可以在项目中创建一个.npmrc文件。如果文件一起提交到Git,配置可以与所有环境共享,有利于多人协作,也可以被CI等第三方工具使用。因此,也是作者推荐的方法。#.npmrcregistry=https://registry.npm.taobao.orgyarn也会读取这个文件,除非你在.yarnrc中覆盖这个配置。#.yarnrcregistry"https://registry.npm.taobao.org"配置二进制文件的镜像地址单纯使用国内npm镜像并不能解决所有问题。最著名的例子:为了简化CSS的编写,许多项目都使用预处理器。在国内,less预处理器比生态更完整的sass处理器更受欢迎的原因之一是sass编译工具node-sass的安装非常困难,所以很多公司、团队和个人开发者决定选择少用。node-sass安装困难的原因是它在npm安装过程之后触发了一个额外的编译过程。它使用托管在https://github.com/sass/node-…的C++编译二进制文件,具体取决于版本。Github使用亚马逊的AWS服务作为CDN。由于一些众所周知的原因,有时在中国大陆无法访问。因此,当该文件下载失败时,会触发本机编译以生成替代二进制文件,这通常会失败(尤其是在Windows7系统上)。很多网上的教程都会建议这时候安装一个C++相关的编译环境,也有人会说“用Linux保平安”。但实际上,只要能解决二进制文件的下载问题,就可以大大提高成功率。淘宝镜像上也提供了相应的二进制包,通过设置环境变量可以使用国内加速。cnpm内置了这个进程,所以可以自动解决这种情况。如果不使用cnpm,通过命令行设置环境变量:#全局配置,对单个设备永久生效yarnconfigsetsass_binary_sitehttps://npm.taobao.org/mirrors/node-sass/#对于单个安装SASS_BINARY_SITE=https://npm.taobao.org/mirrors/node-sass/&&yarnaddnode-sass#oryarnaddnode-sass--sass_binary_sitehttps://npm.taobao.org/mirrors/node-sass/或者类似其配置在.npmrc文件中实现共享配置的效果:electron/phantomjs这个方法也可以用electron来加速,因为他们都允许使用环境变量来设置镜像url。我们可以在https://npm.taobao.org/mirrors查看所有可用的镜像。网上的大部分文章就到此为止了,但这还不是全部。使用bin-wrapper-chinaimagemin是一系列基于C++的图像压缩模块,包含pngquant、mozjpeg等知名库,需要下载node-sass等二进制文件。但是不支持使用环境变量配置镜像仓库url,自编译成功率低很多。这个时候npm和yarn都只能认命,祈祷网络顺畅。没错,cnpm也通过内置处理解决了这种情况。有必要转身用cnpm吗?当然不是,查看源码发现,不少使用二进制文件的模块都会通过bin-wrapper下载编译。所以只要在下载前把bin-wrapper中使用的下载链接换成镜像仓库的url就可以解决问题。作者为此创建了一个工具bin-wrapper-china,将原来的bin-wrapperfork出来,读取cnpm使用的binary-mirror-config获取所有可用的镜像淘宝镜像url,并替换下载文件的链接.这样就可以愉快的使用加速功能了。那么问题来了,如何使用bin-wrapper-china而不是bin-wrapper来执行下载呢?答案是使用yarn的killerfeatureresolutions(npm不支持),它可以让我们在用yarn安装的时候用指定的模块替换另一个模块。具体配置方法如下://package.jsonwithyarn{"resolutions":{"bin-wrapper":"npm:bin-wrapper-china"}}bin-wrapper-china的“模拟”发生在安装过程,bin-wrapper的运行发生在安装后,可以无缝运行。这样可以大大提高imagemin系列的安装成功率。解析详见:https://yarnpkg.com/lang/en/d...https://github.com/yarnpkg/rf...对于支持环境变量的模块,如node-sass,bin-wrapper-china还可以提供对china-bin-env命令的支持,而不是手动环境变量。但是,由于我们不推荐注入yarn或者npm本身,环境变量的注入必须在安装前进行,所以需要的话在项目中手动设置preinstall命令://package.json{"scripts":{//使用npm"preinstall":"npminstallbin-wrapper-china-D&&china-bin-env",//使用yarn"preinstall":"yarnaddbin-wrapper-china-D&&china-bin-env"}}基于preinstall的操作需要提前安装bin-wrapper-china,笔者也希望以后有更好的解决方案。总结由于cnpm的某些功能缺失,我们可能决定弃用它,但它的加速能力正是我们所需要的。总结一下,cnpm做了三件事:使用淘宝npm镜像仓库,加快常规模块的安装。可配置的二进制文件,提前注入环境变量以加速。不可配置的二进制文件,强制替换url以加快下载速度。这也是我们要做的三件事(一般在项目中配置):通过.npmrc文件配置npm仓库地址为国内镜像地址。通过.npmrc文件配置环境变量,或者通过bin-wrapper-china的china-bin-env命令注入环境变量。配置yarn分辨率,使用bin-wrapper-china模拟bin-wrapper实现url替换。当然,如果你确定要使用cnpm,或者你所在的工作网络可以畅通,或者项目不需要安装包含二进制文件的模块(比如我在项目中使用sass来代替node-sass),你不需要考虑这个问题了。虽然本文推荐使用yarn,但其核心流程适用于Node.js生态中的大多数包管理器。有兴趣的读者可以多做探索。相关项目:https://github.com/best-shot/...https://github.com/cnpm/binar...
