锁定Node.js的包管理:Corepack使用指南

发布于:2024-04-26 ⋅ 阅读:(24) ⋅ 点赞:(0)

大家好,我是老纪。

Node.js的生态系统太复杂了,光是流行的包管理器就有多种:npm、yarn classic、yarn berry 和 pnpm。如果再加上Node.js的两个竞争对手Deno与Bun就更复杂了,当然,后者不在我们今天的讨论范围。

之所以形成今天的局面,根本原因是npm太拉胯了,从诞生之初就有各式各样的问题,导致社区不得自起炉灶,有了yarnyarnv2起放弃了node_modules结构,我们可以称之为yarn berry,之前的v1yarn classic)和pnpm。npm这个嫡长子也没有躺平摆烂,同样很努力地改进性能、改变解析策略,于是隔几个版本可能就不向下兼容了。关键是努力了好久,还是不如yarnpnpm做的好,以至于Node.js官方想要把它放弃~

image.png

在这样的大背景下,我们在日常开发中,同一个工程,同一个团队的成员可能面临这样的局面:

  1. A同学使用npm,B同学使用yarn,C同学使用pnpm,各自安装的依赖版本都不一样,运行的结果可能千奇百怪

  2. 领导要求同学们统一使用pnpm,于是A同学使用pnpm v6,B同学使用pnpm v8,这时可能有两种情况:

    1. A同学安装失败,这说明pnpm有了破坏性变更(仅是举例)
    2. A同学安装成功,但是pnpm-lock.yaml与B同学上传的不一样,当他提交后,B同学又发现自己安装后这个文件又变了,因为里面记录的lockfileVersion不一样

所以,如何锁定团队的包管理器甚至锁定其版本,成为团队代码管理的一个重要课题。

本文的主角 正是为解决这个问题而生。它是Node.js官方推出的一个实验性工具,用于帮助管理包管理器的版本。它为每个支持的包管理器暴露了二进制代理,当调用时,将识别当前项目配置的任何包管理器,如有需要则下载,并最终运行它。

需要注意的是,虽然Corepack与Node.js(v16.9.0v14.19.0起)默认分发,但Corepack管理的包管理器不是Node.js分发的一部分,并且在第一次使用时,Corepack会从网络下载最新版本。

下来,本文带你了解下如何使用Corepack,版本号为0.25.2

启用

Corepack随Node.js v16.9.0分发

Corepack随Node.js v16.9.0分发

尽管距离2021年9月发布已经过去了两年半的时间,但Corepack仍处于实验阶段,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.                 │
   │   Changeloghttps://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 ErrorThis 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

离线环境(比如某些要求严格的流水线环境),可以将packinstall结合使用:

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版本乃至包管理工具的版本,前者可以搭配nvm、fnm、pnpm等第三方工具实现自动切换,而Corepack则是Node.js官方推出的与npm解耦的积极尝试,它的使用方法足够简单,后期变更的余地不大,虽然仍处于实验状态,但小伙伴们已经可以用起来了!