关于前端:使用-volta-与-corepack-规范团队在不同项目中使用的-node-版本与-npm-包管理器

10次阅读

共计 8675 个字符,预计需要花费 22 分钟才能阅读完成。

0. 前言

在前端开发团队中,常常存在多个新老我的项目同时开发的状况,这些我的项目他们的 node 版本可能不一样,我的项目中所应用的包管理器也不一样。比方一些老的我的项目可能应用低版本 node 并应用 npm 装置我的项目依赖,而一些新的我的项目则会应用高版本 node 与 pnpm/yarn 来装置我的项目依赖。

如果 node 版本不对立,带来的问题可能就是整个我的项目无奈运行;而如果包管理器不对立,带来的则可能是 package-lock.jsonyarn.lockpnpm-lock.yaml 在每个成员电脑上都不统一的劫难。

之所以是劫难,因为很多我的项目本地明明运行的好好的,然而在其他人电脑上或者线上却无奈失常运行,这都很有可能是因为 lock 文件没有对其导致装置了谬误版本的依赖包!

为了解决这个问题,本文将向你展现如何应用 volta 来治理 node 版本,并用 corepack 来治理包管理器,团队只须要筹备雷同的环境,对以后的我的项目进行简略革新,就能够实现在每个我的项目中主动切换 node 版本与包管理器版本!

1. Volta

Volta 官网形容为一款无障碍的 JavaScript 工具管理器,与 nvm、n 相似的,能够用来治理 Node 版本,但同时又有以下劣势:

  • 能够依据我的项目 package.json 申明的 volta 配置来依据不同的我的项目主动切换 node 版本;
  • volta 也能够间接治理 pnpm 与 yarn(不举荐,倡议如果应用高版本的 node,应用前面的 corepack 来治理包管理器);
  • 当应用 volta 装置的 node 来执行全局装置时,切换 node 版本后,全局装置的包依然存在,并且其运行时所依赖的 node 版本会被固定为装置该包时应用的 node 版本;

1.1 装置

volta 装置只须要执行一行命令:

curl https://get.volta.sh | bash

之后便能够应用 volta 来装置不通版本的 node:

volta install node@18

若想要切换 node 版本,也只需应用 volta install 指令即可

你能够应用 volta list all 查看以后 volta 所曾经装置的内容:

⚡️ User toolchain:

    Node runtimes:
        v14.21.3 (default)
        v16.20.1
        v18.16.1
        v20.3.1

    Package managers:


    Packages:
        serve@14.2.0 (default)
            binary tools: serve
            platform:
                runtime: node@14.21.3
                package manager: npm@built-in

这些内容分为三局部:

  • Node runtimes:你曾经装置的 node 版本,显示 default 即为你以后全局应用的 node 版本;
  • Package managers:你曾经装置的包管理器(这一部分的治理与 corepack 抵触,前面再具体探讨);
  • Packages:应用 npm install --global 装置的全局包,volta 会在此列出,并固定其运行时版本;

1.2 应用 volta 治理我的项目依赖的 node

如果你之前应用的是 nvm,如果你想要为不通的我的项目来标准 node 版本,那么须要在我的项目目录通过创立 .nvmrc 写入 node 版本,并要求开发者在进入我的项目时应用 nvm use 来对其以后应用的 node 版本。这个操作如果想要自动化,就须要编写一个自动化脚本来实现(参考)。

然而对于 volta 来说,这个步骤是及其简略并且齐全自动化的。当要求全团队应用 volta 后,能够间接在我的项目目录(package.json 的目录下)应用如下指令,将以后我的项目所应用的 node 版本固定为 node v18 的 LTS 版本:

volta pin node@18

之后,你就会发现我的项目的 package.json 中被增加上一段:

"volta": {"node": "18.16.1"}

之后当用户进入到以后我的项目中时,volta 就会检测到 package.json 中申明的 node 版本,并且切换至该 node 版本。

1.3 volta 卸载不应用的 node 和包管理器

当你尝试应用 volta uninstall yarn 或者 volta uninstall node 时,会呈现暂无奈反对卸载的提醒:

error: Uninstalling node is not supported yet.

因而须要到 ~/.volta/tools/image 手动删除曾经下载的 npm 或者 yarn 等,参考。

1.4 volta 的原理

volta 的原理并不简单,实质上就是通过覆写二进制文件的执行指令到 volta 的处理程序中,而后 volta 就能够调用正确的 node 版本,或者调用全局装置的二进制文件并为其指定 node 版本。

咱们能够应用 which node 来查看以下 node 的执行地位,会发现其执行地位为用户目录下的 .volta/bin/node 中。

咱们在来查看一下全局装置的包,比方咱们应用 npm install serve -g 装置的 serve 指令,调用 which serve 能够发现其执行地位同样为 ~/.volta/bin 目录。

咱们切换到该目录后,就能够查看到这些可执行文件:

node npm npx serve volta volta-migrate volta-shim

能够发现,咱们通过全局装置指令装置的二进制文件会被放到这个地位,node 和 npm 的执行文件也在这个地位。但实际上另有玄机,咱们能够应用 ls -l 查看一下文件的详细信息:

total 37008
lrwxr-xr-x  1 username  staff    39B Jul  4 14:49 node -> /Users/username/.volta/bin/volta-shim
lrwxr-xr-x  1 username  staff    39B Jul  4 14:49 npm -> /Users/username/.volta/bin/volta-shim
lrwxr-xr-x  1 username  staff    39B Jul  4 14:49 npx -> /Users/username/.volta/bin/volta-shim
lrwxr-xr-x  1 username  staff    39B Jul  5 19:12 serve -> /Users/username/.volta/bin/volta-shim
-rwxr-xr-x  1 username  staff   7.3M Jan 25 05:38 volta
-rwxr-xr-x  1 username  staff   4.4M Jan 25 05:37 volta-migrate
-rwxr-xr-x  1 username  staff   6.4M Jan 25 05:37 volta-shim

这些可执行的二进制文件都被应用连接符软连贯到了 volta-shim 这个可执行文件下来。

因而 volta 背地主动切换 node 版本以及治理全局包的魔法实际上就是:当应用 Volta 时,npm、node 以及其余全局包的这些二进制文件被重定向到 .volta/bin 目录下的对应可执行文件,而这些可执行文件实际上都是 .volta/bin/volta-shim 所创立的软连贯。volta-shim 自身是一个非凡的脚本,他次要做了如下这些事件:

  • 如果是 node、npm、yarn 等指令,监测当前工作控件是否被 volta pin 指定了 node 版本和包管理器的版本,如果是,则将指令定向到指标版本;
  • 如果是 serve 这种由 npm 装置的可执行文件,则定向到该可执行文件,并且 应用装置该可执行文件时的 node 版本 来执行该指令。

2. Corepack

留神:corepack 只实用于 node@16.9.0 以上的版本,如果你的团队 node 版本低于此版本,同时我的项目又应用了 yarn/pnpm 来进行包治理,那么应用 corepack 可能存在问题,能够思考应用 volta 的包管理器的治理性能。如果非要应用,能够参考 3.3 节中的计划。

corepack 是 node 官网出的一个治理 node 包管理器的管理器,其曾经内置于 node@20 版本中,与 npm 一样作为被默认装置的指令工具,但默认没有被启用。

其诞生背景是因为 npm 自身的不思进取,导致社区呈现了 yarn、pnpm 这些更优良的包管理器工具,然而这些包管理器工具在不同的我的项目中又有可能应用不同的版本,因而标准我的项目中应用的包管理器也和标准我的项目所应用的 node 版本一样重要。

毕竟在团队中,谁都不想 lock 文件在每个人的电脑上都有各自的版本!

2.1 装置

如果你的团队应用的是 node@20,那么 corepack 指令则曾经被默认装置。如果你是用的是其余版本的 node(最低 node@16.9.0),则须要手动执行 npm install corepack -g 来装置。

装置后的 corepack 默认是被禁用的,如果你想要启用 corepack 则须要先卸载全局装置的包管理器:

npm uninstall yarn -g
npm uninstall pnpm -g

而后执行:

corepack enable
corepack prepare --all

首先,corepack 会被启用,在你的 /usr/local/bin/ 目录下创立 pnpm、pnpx、yarn、yarnpkg 这几个可执行文件,让你能够应用 pnpm 和 yarn 的指令。实际上,这些指令也是一个软连贯,会连贯到 corepack 的处理程序(其实与 volta 的原理相似),以让 corepack 能够应用正确的包管理器版本;

之后应用 corepack prepare --all 指令会下载最新的 pnpm 和 yarn 的稳定版,此时你就能够失常在全局应用 yarn 和 pnpm 了。

如果你想切换全局装置的 pnpm 和 yarn,能够应用上面的指令:

# 将全局应用 pnpm 版本切换到 pnpm@6.35.1
corepack prepare pnpm@6.35.1 --activate

留神:corepack 指定包管理器版本的时候必须应用 @x.y.x 来明确三位版本号

2.2 应用 corepack 治理我的项目应用的包管理器

与 volta 相似的,corepack 也是通过辨认我的项目 package.json 中申明的配置来主动切换包管理器的,但须要手动增加:

{"packageManager": "pnpm@8.6.6"}

这样,就胜利指定了我的项目应用的 pnpm 版本为 8.6.6,当咱们应用 pnpm 指令的时候,corepack 会主动装置对应版本,并调用改版本。

此外,如果读取到无效的 packageManger 配置,corepack 还会阻止用户应用谬误的包管理器来装置,比方如果用户在下面配置的我的项目中应用 yarn install,那么就会呈现报错:

Usage Error: This project is configured to use pnpm

$ yarn ...

corepack 默认不会托管 npm,也不倡议这么做(因为 node 版本与 npm 版本曾经强绑定了),因而不会拦挡 npm install 的指令

3. Volta 与 Corepack 联合应用

3.1 为什么非要应用 Corepack?

当你看到这里可能会有疑难,volta 自身是反对同时治理 node 与包管理器,但为什么还要应用 corepack?那么我只能说 volta 自身的包治理是有缺点的,而 corepack 是将来

应用 corepack 曾经被 node 官网视为一个 标准,曾经集成在 Node 的最新发行版本中,目前残缺的反对 yarn 和 pnpm 的切换,yarn 和 pnpm 在初始化我的项目的时候也会将 packageManager 写入到 package.json 中,corepack 必然是一个趋势。所以对于包管理器的治理来说,该当尽量应用 Corepack 而非 Volta。

综上,一个比拟举荐的做法是:

  • 应用 volta 治理 node,以及全局装置的 npm 包
  • 应用 corepack 治理包管理器

3.2 Volta 与 Corepack 之间的抵触问题

因为 volta 和 corepack 对于包管理器的治理都是基于 shim 的,也就是说他们都会拦挡 yarn 以及 pnpm 指令,因而两个管理器之间存在抵触,你能够能会遇到以下问题:

  • volta 装置了高版本 node,然而 corepack 指令无奈应用;
  • 应用 volta 治理的 node 进行全局装置 corepack,在应用 corepack 治理的 yarn/pnpm 执行 package.json 中的脚本时,node 版本也会被限度为 volta 锁定 corepack 时的版本;
  • 通过其余路径装置了 corepack,但就是无奈应用 corepack 治理的 yarn/pnpm,当应用 yarn 指令时,会呈现 volta 的正告;

要想解决这个问题,肯定要遵循如下的准则:

  1. 不要应用 volta 治理的 node 来全局装置 corepack
  2. 让 corepack 的 shim 笼罩掉 volta 的 shim

以下以 MacOS 和 Ubuntu 来演示一下如何同时装置 volta 与 corepack 并解决其抵触:

MacOS 的装置流程

前置条件:最好先卸载设施上所有的包管理器以及 node

首先,如果装置了 volta,依照以下步骤 卸载 volta:

rm -rf ~/.volta

而后应用 homebrew 装置 corepack:

brew install corepack

因为 corepack 依赖 node,brew 会在你的电脑上装置 node@20,不过没关系,后续咱们应用 volta 治理 node,装置的这个 node 不会被应用,也不会影响咱们应用 volta 切换 node 版本

测试一下 corepack 指令,并将其启用:

corepack enable
corepack prepare --all

装置 volta:

curl https://get.volta.sh | bash

应用 volta 装置 node:

volta install node

装置完 node 后能够检查一下 pnpm/yarn 指令是否被 volta 拦挡:

which yarn
# 如果输入以下门路,阐明正在应用 corepack 治理 yarn
/usr/local/bin/yarn

后续就不要应用 volta 装置任何包管理器,也不要执行 npm install yarn -g 或者 npm install pnpm -g,否则 corepack 可能生效。

如果 corepack 生效,同时应用 which yarn 显示的 yarn 的执行文件在 ~/.volta/bin/yarn 的地位,能够应用 corepack enable --install-directory ~/.volta/bin 来强行将 coreapck 的 shim 笼罩到 volta 的 shim 上。

Linux 的装置流程

同样的,在装置 corepack 前须要卸载 volta:

rm -rf ~/.volta

因为 Ubuntu 等 Linux 零碎没有 homebrew,同时零碎的装置源中也没有 corepack,所以咱们要通过装置 node@20 的形式来装置 corepack,输出以下指令来增加 node@20 的装置源,并装置 node(其余 Linux 零碎能够查看 这里):

curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - &&\
sudo apt-get install -y nodejs

测试一下 corepack 指令,并将其启用:

corepack enable
corepack prepare --all

装置 volta:

curl https://get.volta.sh | bash

应用 volta 装置 node:

volta install node

与 MacOS 不同的是,当你重启终端后会发现 corepack 生效了,具体的体现为,当你应用 yarn -v 时会呈现如下提醒:

Volta error: Yarn is not available.

Use `volta install yarn` to select a default version (see `volta help install` for more info).

能够应用 which yarn 来查看 yarn 的执行门路变为了:

/root/.volta/bin/yarn

在装置了 corepack 但未装置 volta 时,执行门路为 /usr/bin/yarn

咱们能够应用如下指令强行让 corepack 的 shim 笼罩掉 volta 的 shim:

corepack enable --install-directory ~/.volta/bin

进入到 ~/.volta/bin 目录下,应用 ls -l 指令,咱们就会发现 volta 的 pnpm、yarn 相干的指令都被指向到了 corepack 的 shim:

lrwxrwxrwx 1 root root   51  7 月  6 17:08 pnpm -> ../../../usr/lib/node_modules/corepack/dist/pnpm.js
lrwxrwxrwx 1 root root   51  7 月  6 17:08 pnpx -> ../../../usr/lib/node_modules/corepack/dist/pnpx.js
lrwxrwxrwx 1 root root   51  7 月  6 17:08 yarn -> ../../../usr/lib/node_modules/corepack/dist/yarn.js
lrwxrwxrwx 1 root root   54  7 月  6 17:08 yarnpkg -> ../../../usr/lib/node_modules/corepack/dist/yarnpkg.js

这样,yarn/pnpm 的管理权就又从新回到了 corepack 手上,能够欢快的应用 corepack 了。

3.3 低版本 node 我的项目中无奈应用 corepack

如果你的某个我的项目低于 node@16.9.0,并且这个我的项目应用了 pnpm 或者 yarn 来作为包管理器治理我的项目依赖,那么当你装置并启用了 corepack 后你会发现无奈应用 pnpm 和 yarn 指令了,会呈现如下报错:

/usr/local/Cellar/corepack/0.19.0/libexec/lib/node_modules/corepack/dist/lib/corepack.cjs:39787
      process.exitCode ??= code;
                       ^^^

SyntaxError: Unexpected token '??='
    at wrapSafe (internal/modules/cjs/loader.js:1029:16)
    at Module._compile (internal/modules/cjs/loader.js:1078:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1143:10)
    at Module.load (internal/modules/cjs/loader.js:979:32)
    at Function.Module._load (internal/modules/cjs/loader.js:819:12)
    at Module.require (internal/modules/cjs/loader.js:1003:19)
    at require (internal/modules/cjs/helpers.js:107:18)
    at Object.<anonymous> (/usr/local/Cellar/corepack/0.19.0/libexec/lib/node_modules/corepack/dist/pnpm.js:2:1)
    at Module._compile (internal/modules/cjs/loader.js:1114:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1143:10)

这是因为 corepack 自身是依赖高版本 node 运行的,当以后零碎环境的 node 低于 16.9.0 时,当用户应用 pnpm/yarn 指令会调用 corepack 的 shim,而后执行 corepack 的代码,然而因为以后零碎环境的 node 版本低于 corepack 的要求,因而就会呈现运行谬误。

解决这个问题最好的计划是将 node 降级,如果是在无奈降级,则能够尝试以下计划:

  • 【最笨的计划,不举荐应用】切回高版本 node,并禁用 corepack,而后回到低版本 node,全局装置 yarn/pnpm(回到高版本 node 前卸载掉全局装置的 yarn/pnpm,而后从新启用 corepack);
  • 【举荐网速快的应用】应用 npx yarnnpx pnpm 指令(还能够指定版本,比方 npx pnpm@6)来绕过 corepack,这种计划最便捷,然而因为是应用 npx,每次都须要从新下载 pnpm 和 yarn,网速快的话能够忽视;
  • 【配置简单,但应用比拟不便】应用 volta install 装置一个你须要版本的包管理器,比方 volta install pnpm@6,而后你能够在 ~/.volta/tools/image/packages/pnpm/bin 目录下找到一个 pnpm 的可执行文件,你能够在你的 .bashrc 或者 .zshrc 应用 alias 创立一个指令别名,如 alias pnpm@volta='~/.volta/tools/image/packages/pnpm/bin/pnpm',而后就能够在须要的时候应用 pnpm@volta 来代替执行 pnpm 指令,如果须要切换版本,则从新应用 volta install 装置你须要的版本即可;
正文完
 0