大家好,我是老纪。
Node.js的生态系统太复杂了,光是流行的包管理器就有多种:npm、yarn classic、yarn berry 和 pnpm。如果再加上Node.js的两个竞争对手Deno与Bun就更复杂了,当然,后者不在我们今天的讨论范围。
之所以形成今天的局面,根本原因是npm
太拉胯了,从诞生之初就有各式各样的问题,导致社区不得自起炉灶,有了yarn
(yarn
从v2
起放弃了node_modules
结构,我们可以称之为yarn berry
,之前的v1
是yarn classic
)和pnpm。npm这个嫡长子也没有躺平摆烂,同样很努力地改进性能、改变解析策略,于是隔几个版本可能就不向下兼容了。关键是努力了好久,还是不如yarn
与pnpm
做的好,以至于Node.js官方想要把它放弃~
在这样的大背景下,我们在日常开发中,同一个工程,同一个团队的成员可能面临这样的局面:
-
A同学使用npm,B同学使用yarn,C同学使用pnpm,各自安装的依赖版本都不一样,运行的结果可能千奇百怪
-
领导要求同学们统一使用pnpm,于是A同学使用pnpm v6,B同学使用pnpm v8,这时可能有两种情况:
- A同学安装失败,这说明pnpm有了破坏性变更(仅是举例)
- A同学安装成功,但是
pnpm-lock.yaml
与B同学上传的不一样,当他提交后,B同学又发现自己安装后这个文件又变了,因为里面记录的lockfileVersion
不一样
所以,如何锁定团队的包管理器甚至锁定其版本,成为团队代码管理的一个重要课题。
本文的主角 Corepack 正是为解决这个问题而生。它是Node.js官方推出的一个实验性工具,用于帮助管理包管理器的版本。它为每个支持的包管理器暴露了二进制代理,当调用时,将识别当前项目配置的任何包管理器,如有需要则下载,并最终运行它。
需要注意的是,虽然
Corepack
与Node.js(v16.9.0
、v14.19.0
起)默认分发,但Corepack
管理的包管理器不是Node.js分发的一部分,并且在第一次使用时,Corepack
会从网络下载最新版本。
下来,本文带你了解下如何使用Corepack
,版本号为0.25.2
。
启用
Corepack随Node.js v16.9.0分发
尽管距离2021年9月发布已经过去了两年半的时间,但Corepack
仍处于实验阶段,Node.js社区仍不能默认启用它,详见这篇文章《抛弃 NPM ? Node.js 社区正为启用新的包管理方式争论不休!》。
它的启用与关闭非常简单:
# 启用
$ corepack enable
# 关闭
$ corepack disable
我们新建一个工程来看下具体怎么使用。
锁定
我们以锁定pnpm的具体版本v6.0.0
为例,有两种方式。
手动添加
手动在package.json
中添加packageManager
字段:
{
"packageManager": "pnpm@6.0.0"
}
当我们在这个工程下执行pnpm
相关命令时,就会触发Corepack
,如果之前没有下载就会提示你下载:
root@debian:/wk/nodejs/test# pnpm -v
Corepack is about to download https://registry.npmjs.org/pnpm/-/pnpm-6.0.0.tgz.
Do you want to continue? [Y/n]
╭──────────────────────────────────────────────────────────────────╮
│ │
│ Update available! 6.0.0 → 8.15.5. │
│ Changelog: https://github.com/pnpm/pnpm/releases/tag/v8.15.5 │
│ Run pnpm add -g pnpm to update. │
│ │
│ Follow @pnpmjs for updates: https://twitter.com/pnpmjs │
│ │
╰──────────────────────────────────────────────────────────────────╯
Packages: +9
+++++++++
Packages are hard linked from the content-addressable store to the virtual store.
Content-addressable store is at: /root/.pnpm-store/v3
Virtual store is at: node_modules/.pnpm
Progress: resolved 9, reused 0, downloaded 9, added 9, done
root@debian:/wk/nodejs/test# pnpm -v
6.0.0
但是当你试图使用yarn
时就会报错:
root@debian:/wk/nodejs/test# yarn -v
Usage Error: This project is configured to use pnpm
$ yarn ...
使用命令
我们可以使用命令corepack use
:
root@debian:/wk/nodejs/test# corepack use pnpm@6.0.0
Installing pnpm@6.0.0 in the project...
Packages: +9
+++++++++
Packages are hard linked from the content-addressable store to the virtual store.
Content-addressable store is at: /root/.pnpm-store/v3
Virtual store is at: node_modules/.pnpm
Progress: resolved 9, reused 9, downloaded 0, added 9, done
再看package.json
文件中的配置已经修改了,还携带了具体版本的hash
值:
{
"packageManager": "pnpm@6.0.0+sha256.91ac442f0d6c4545421d6a0c1c3ecbcb717df6ae6922d8b7693ec5bfd9144d5c"
}
锁定yarn
也是同样的处理,这里就不水字数了。
升级
corepack up
可以升级当前项目的版本,稍微有些特殊的是,它并不是升级到最新版本,而是当前大版本的最新可用版本。
比如我们上面例子中用的是6.0.0
,那么会升级到6.35.1
:
$ corepack up
Installing pnpm@6.35.1 in the project...
全局安装
我们可以通过运行以下命令来全局安装最新版本:
corepack install -g pnpm@*
corepack install -g pnpm@8
corepack install -g yarn@stable
离线环境(比如某些要求严格的流水线环境),可以将pack
与install
结合使用:
root@debian:/wk/nodejs/test# corepack pack pnpm
Adding pnpm@9.0.0-beta.2 to the cache...
Packing the selected tools in corepack.tgz...
All done!
root@debian:/wk/nodejs/test# corepack install -g ./corepack.tgz
Installing pnpm@9.0.0-beta.2...
总结
正如我另一篇文章《如何锁定并自动切换Node.js版本?》所说,Node.js生态的复杂性决定了团队开发者必须锁定Node.js版本乃至包管理工具的版本,前者可以搭配nvm、fnm、pnpm等第三方工具实现自动切换,而Corepack
则是Node.js官方推出的与npm解耦的积极尝试,它的使用方法足够简单,后期变更的余地不大,虽然仍处于实验状态,但小伙伴们已经可以用起来了!
原文链接:https://juejin.cn/post/7352739150242496527 作者:纪轻昀