如何让 YARN 支持 CNPM 的完整加速

2019-12-02 admin

国内的前端开发人或多或少都了解过 cnpm ,但项目开发因人而异,很多时候不会或不能使用 cnpm ,不计其数的项目在使用 yarn 或者其他包管理器安装依赖。本文将介绍这样的情况下如何加速二进制文件下载。

在前一段时间发布的 Github Octoverse 2019 报告中,JavaScript 继续蝉联最受欢迎编程语言。JavaScript 生态的保持繁荣,与 Node.js 的流行密不可分。而说到 JavaScript 生态,不得不提到 npm,npm 不仅是前端开发首选的包管理器,也是除了 Github 之外最重要的代码共享途径。Snyk 2019 开源安全年报中指出,npm 生态的包数量远超其他包管理器。

各个包管理器生态的包总数

现阶段,主流的前端开源项目在发布时都会使用 npm 的在线托管服务 https://www.npmjs.com/。但开发者能够使用的包管理器却不止 npm 一个,来自开源社区的 yarn 和 pnpm 正在被越来越多人使用,它们最显著的优点就是加快依赖的安装速度。对于中国开发者,由阿里巴巴开源的 cnpm 也是一个重要的选择。

关于 CNPM 的那些事

reactvue 引领的前端工程化开发在国内大规模流行以来,前端项目的依赖安装成为了日常工作的重要组成部分。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 和其他第三方工具使用。因此也是笔者推荐使用的方法。

# .npmrc
registry = https://registry.npm.taobao.org

yarn 同样也会读取这个文件,除非你在 .yarnrc 中覆盖了这一配置。

# .yarnrc
registry "https://registry.npm.taobao.org"

配置二进制文件的镜像地址

单纯的使用国内 npm 镜像并不能解决所有问题。最知名的例子:

为了简化 CSS 的编写,许多项目都会使用预处理器。在国内,预处理器less比生态更加完整的 sass 处理器流行的原因之一,便是因为 sass 的编译工具 node-sass 的安装曾经十分困难,许多公司、团队和个人开发者因此决定了选型使用 less

node-sass 之所以难以安装,是它在 npm 安装流程之后,还会触发一个而外的编译流程。其中使用了 C++ 编译的二进制文件,该文件根据版本托管在 https://github.com/sass/node-… 。Github 使用了亚马逊的 AWS 服务作为 CDN,由于某些众所周知的原因,在中国大陆有时会无法访问。于是乎在该文件下载失败后,就会触发本机编译以生成替代的二进制文件,这一过程往往以失败告终(尤其是在 Windows 7 系统)。很多网络教程这时候会建议安装 C++ 相关的编译环境,也有人会说 “用 Linux 保平安”。

但实际上只要能解决二进制文件的下载问题就能大大提高成功率。淘宝镜像上也提供了相应的二进制包,通过设置环境变量使用国内加速。cnpm 内置了这一过程,所以可以自动解决这一情况。

不使用 cnpm 的话,则通过命令行设置环境变量:

# 全局配置,单台设备上永久生效
yarn config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/

# 针对单次安装
SASS_BINARY_SITE=https://npm.taobao.org/mirrors/node-sass/ && yarn add node-sass
# or
yarn add node-sass --sass_binary_site https://npm.taobao.org/mirrors/node-sass/

或者同样将其配置在 .npmrc 文件中达到分享配置的效果:

# .npmrc
sass_binary_site = https://npm.taobao.org/mirrors/node-sass/
electron_mirror = https://npm.taobao.org/mirrors/electron/

phantomjselectron 等同样可以使用此方法加速,因为他们都允许使用环境变量设置镜像 url。我们可以在 https://npm.taobao.org/mirrors 上查看所有可用的镜像。

网络上绝大多数的文章也就到此为止了,然而这还不是全部。

使用 bin-wrapper-china

imagemin 是一系列基于 C++ 实现的图片压缩模块,其中包含了 pngquantmozjpeg 等知名库,和 node-sass 一样需要下载二进制文件。然而它却没有不支持使用环境变量配置镜像仓库 url,自主编译的成功率也要低得多。这时候无论是 npm 还是 yarn 都只能听天由命祈祷网络畅通。

没错,cnpm 通过内置的处理也解决了这种情况,那是不是要吃回头草用 cnpm 呢?

当然不用,查看源码可以发现,相当一部分使用了二进制文件的模块,都会通过 bin-wrapper 执行下载和编译。于是乎只要能在下载之前将 bin-wrapper 内使用的下载链接替换成镜像仓库的 url,问题便迎刃而解。

笔者为此创建了一个工具 bin-wrapper-china,该工具 fork 了原版的 bin-wrapper,并读取了 cnpm 所使用的 binary-mirror-config 获取所有可用的镜像淘宝镜像 url,替换下载文件的链接。这样就可以愉快地使用加速功能。那么问题来了,怎样用 bin-wrapper-china 代替 bin-wrapper 执行下载呢?

答案是使用 yarn 的杀手级功能 resolutions (npm 不支持),它允许我们用 yarn 执行安装时,用指定的模块替换另一个模块,具体的配置方法如下:

// package.json with yarn
{
  "resolutions": {
    "bin-wrapper": "npm:bin-wrapper-china"
  }
}

bin-wrapper-china 的“冒名顶替”发生在安装过程之中,bin-wrapper 的运行发生在安装之后 ,所以能够无缝的运行。这样一来 imagemin 系列的安装成功率便能大为提高,关于 resolutions 的相关说明,详见:

对于支持环境变量的模块,例如 node-sass 等,bin-wrapper-china 也能提供了 china-bin-env 命令代替手动环境变量的支持。但由于我们不建议注入 yarn 或 npm 本身,而环境变量的注入必须在安装之前执行,故在有需要的情况下在项目内手动设置 preinstall 命令:

// package.json
{
  "scripts": {
    // Use npm
    "preinstall": "npm install bin-wrapper-china -D && china-bin-env",
    // Use yarn
    "preinstall": "yarn add bin-wrapper-china -D && china-bin-env"
  }
}

基于 preinstall 的操作需要 bin-wrapper-china 的提前安装,笔者也希望后续有更好的解决方案。

总结

由于 cnpm 的一些功能缺失,我们可能会决定弃用它,但是它的加速能力又是我们所需要的。

总结起来,cnpm 做了三件事:

  • 使用淘宝 npm 镜像仓库加速常规模块的安装。
  • 可配置的二进制文件,提前注入环境变量进行加速。
  • 不可配置的二进制文件,强行替换 url 加速器下载。

这也是我们要做的三件事(通常配置在项目中):

  • 通过 .npmrc 文件配置 npm 仓库地址为国内镜像地址。
  • 通过 .npmrc 文件配置环境变量,或通过 bin-wrapper-chinachina-bin-env 命令注入环境变量。
  • 配置 yarn resolutions, 用 bin-wrapper-china 冒充 bin-wrapper 实现 url 替换。

当然了,如果你下定决心使用 cnpm ,或者所处的工作网络能够畅通无阻,或者项目不需要安装含二进制文件的模块(例如笔者在项目中用 sass 替换 node-sass),就不需要考虑这问题了。本文虽然推荐使用 yarn ,但其核心流程适用于大多数 Node.js 生态内的包管理器,各位读者有兴趣可以做更多探索。

相关项目:

[转载]原文链接:https://segmentfault.com/a/1190000021168459

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-80250.html

文章标题:如何让 YARN 支持 CNPM 的完整加速

相关文章
10个强大的纯CSS3动画案例分享
我们的网页外观主要由CSS控制,编写CSS代码可以任意改变我们的网页布局以及网页内容的样式。CSS3的出现,更是可以让网页增添了不少动画元素,让我们的网页变得更加生动有趣,并且更易于交互。本文分享了10个非常炫酷的CSS3动画案例,希望大家...
2015-11-16
v-charts | 饿了么团队开源的基于 Vue 和 ECharts 的图表工具
在使用echarts生成图表时,经常需要做繁琐的数据类型转化、修改复杂的配置项,v-charts的出现正是为了解决这个 痛点。基于Vue2.0和echarts封装的v-charts图表组件,只需要统一提供一种对前后端都友好的数据格式 设置简...
2018-05-24
从2014年的发展来展望JS的未来将会如何
<font face="寰�杞�闆呴粦, Arial, sans-serif ">2014骞达紝杞�浠惰�屼笟鍙戝睍杩呴€燂紝鍚勭�嶈��瑷€灞傚嚭涓嶇┓锛屼互婊¤冻鐢ㄦ埛涓嶆柇鍙樺寲鐨勯渶姹傘€傝繖浜涜��...
2015-11-12
12个你未必知道的CSS小知识
虽然CSS并不是一种很复杂的技术,但就算你是一个使用CSS多年的高手,仍然会有很多CSS用法/属性/属性值你从来没使用过,甚至从来没听说过。 1.CSS的color属性并非只能用于文本显示 对于CSS的color属性,相信所有Web开发人员...
2015-11-12
JS中的语音合成——Speech Synthesis API
JS中的语音合成——Speech Synthesis API 简介 HTML5中和Web Speech相关的API实际上有两类,一类是“语音识别(Speech Recognition)”,另外一个就是“语音合成(Speech Synthes...
2018-05-17
ajax为什么令人惊异?ajax的优缺点
使用Ajax的最大优点,就是能在不更新整个页面的前提下维护数据。这使得Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变的信息。 Ajax不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。就像DHT...
2015-11-12
HTML5的5个不错的开发工具推荐
HTML5规范终于在今年正式定稿,对于从事多年HTML5开发的人员来说绝对是一个重大新闻。数字天堂董事长,DCloud CEO王安也发表了文章,从开发者和用户两个角度分析了HTML对两个人群的优势。其实,关于HTML5的开发工具,我们以往的...
2015-11-12
JavaScript教程:JS中的原型
Keith Peters 几年前发表的一篇博文,关于学习没有“new”的世界,其中解释了使用原型继承代替构造函数。两者都是纯粹的原型编码。 标准方法(The Standard Way) 一直以来,我们学习的在 JavaScript 里创建对...
2015-11-12
layui表格checkbox选择全选样式及功能的实
在之前的版本,默认复选框是要有值得,默认为“勾选”两个字,在表格里用来做选择不适合,很难改,还好layui升级后,可以支持不写name值,来适应表格中的选择操作。 1、layui版本号为 v1.0.9 rls版本(当前最新版本) <s...
2018-03-08
AJAX的浏览器支持
AJAX 的要点是 XMLHttpRequest 对象。 不同的浏览器创建 XMLHttpRequest 对象的方法是有差异的。 IE 浏览器使用 ActiveXObject,而其他的浏览器使用名为 XMLHttpRequest 的 Jav...
2015-11-12
回到顶部