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

国内的前端开发人或多或少都了解过 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-sass/releases 。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 生态内的包管理器,各位读者有兴趣可以做更多探索。

相关项目:

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

推荐阅读更多精彩内容