npm 也慌了?
起因
因为 npm 的种种问题,我很早就换成了 pnpm 和 yarn(然而其实 npm 也在应用),曾经很久没有关注 npm 的性能更新了。最近无意间进入 Node18 版本的装置目录,发现其除了惯例的 node,npm 等默认装置了一个新的包corepack
,这个就是明天我要分享的货色了。
注: 我因为 18 版本的 node 上发现了这个包,目前最新 lts 曾经是 20 了,最新都 21 了。起初去追溯其历史发现其曾经在 14.21.3 上就有了,然而 14.0.0 没有,没再具体去查。
这是一个什么货色呢?来看看官网介绍。
Corepack 是一个零运行时依赖的 Node.js 脚本,用作 Node.js 我的项目与其开发过程中所需的软件包管理器之间的桥梁。从理论角度来看,Corepack 容许您在 不装置Yarn、npm 和 pnpm 的状况下应用它们。
在构建软件包时,只需像平时一样应用您的包管理器即可。在 Yarn 我的项目中运行,在 pnpm 我的项目中运行,在 npm 我的项目中运行。Corepack 将捕捉这些调用,并依据状况进行解决:
- 如果本地我的项目已配置您要应用的包管理器,Corepack 将静默地下载并缓存最新的兼容版本。
- 如果本地我的项目配置的是不同的包管理器,Corepack 将要求您应用正确的包管理器再次运行命令,从而防止毁坏您的安装文件。
- 如果本地我的项目没有配置任何包管理器,Corepack 将假设您晓得本人在做什么,并应用作为“已知良好版本”的固定包管理器版本。
我之前发过一篇文章说了从 npm 到 yarn,再到 pnpm 的历史和我集体的一些了解,不理解的能够去看看。简略来说,因为一些大牛不满 npm 的性能或者不满其模块组织形式,或者不满其它什么中央,造了一个有一个轮子,在持续应用 npm 仓库源的根底上产生了比拟闻名的 yarn 以及 pnpm。尽管 npm 感觉到压力,不断改进本人的毛病,学习其它工具的长处,然而用户必定还是被分流不少,而后以下是我的猜想:预计 npm 发现也阻止不了用户的分流了,打不过就退出,你爱用啥用啥,我间接出一个包管理工具的管理工具,另辟蹊径,我间接去治理 npm,pnpm 以及 yarn。这个工具就是Corepack
.
Corepack 是一种简化 Node.js 我的项目依赖治理的工具,它提供了一种便捷的形式,使您能够在开发过程中应用不同的包管理器,如 Yarn、npm 和 pnpm,而无需当时装置它们 。通过应用Corepack
,您能够在我的项目中间接运行相似于yarn install
、npm install
或pnpm install
等命令,而不用放心在开发环境中装置和配置这些包管理器。
总结一下:
- npm 又造轮子了,这个轮子用来治理 npm,yarn 和 pnpm,联合 package.json 配置,咱们能够限定我的项目要应用的工具。
- 对立包管理器,不必手动保护包管理器,间接应用反对的包管理器命令即可。看官网介绍那段文字,咱们不须要装置 yarn 和 pnpm 状况下也能用 yarn 和 pnpm?
Corepack
启用
咱们上边官网介绍那一段,有一句话 容许您在不装置 Yarn、npm 和 pnpm 的状况下应用它们
。这句话其实通知咱们很重要的事,以前咱们装置完 node,而后须要应用 pnpm 或者 yarn,那么须要顺次装置一遍。而从 node 引入Corepack
后,看意思不须要再去装置了(当然不是 node 默认曾经装置了,而是用的时会去静默下载安装到 Corepack 模块外部)。那么怎么用呢?
因为 Corepack
可能还处于 Experimental 阶段,所以性能默认是敞开的,须要咱们明确开启能力应用,它将在二进制文件旁边设置环境中的符号链接(并在必要时笼罩现有的符号链接)。
# 开启
corepack enable
corepack enable npm #npm 须要独自开启,不倡议开启
#敞开
corepack disable
corepack disable npm #npm 须要独自敞开,不倡议开启,如果开启了,敞开也无奈还原初始状态,而是删除了 corepack 外面的链接
留神:
- corepack enable 开启后默认会装置 yarn 和 pnpm 的最新版,如果您的 node 版本是 14,yarn 或者 pnpm 的最新版可能要求会比 14 高,这就陷入一个你启用了,应用时又说你版本太低的问题。我是间接 18 上装置的。
- 这里留神一下,npm 还是比拟无耻的,它要治理 yarn 和 pnpm,然而 npm 有点特权(兴许是因为处于测试阶段或者本人 npm 的版本兼容问题),npm 也要启用须要独自执行 corepack enable npm,去替换图中的全局 npm 的软链,不然咱们后边应用它治理时就会发现,yarn 和 pnpm 都能够阻止,它本人畅行无阻。( 这外面还有个大坑,这个命令审慎操作,请看前面
问题 1
) - 倡议不要开启
corepack enable npm
。起因有上面 问题 1 ,还有一个问题就是如果你应用 nvm 或者一些进入目录,可能你设置了一些默认执行 npm 命令的一些脚本,例如 nvm 主动切换等等,一旦你配置的包管理器是pnpm
或者yarn
,那么 npm 必定会执行报错。可能还有其它各种各样的奇怪问题。
我以 Node v18.0.0 为例,在咱们未开启时,就是下面第一张图。当咱们执行完开启命令:
发现主动链接了 pnpm 和 yarn 的执行脚本,而后你应用 yarn 或者 pnpm 命令时,会主动在 corepack 目录下载对应工具版本。
咱们也发现 npm 还是原来的模块地址,它不会被动更换链接,除非你执行corepack enable npm
。
我也能了解为啥官网手动装置提醒外面,让先卸载本人装置的 yarn 和 pnpm,因为它会本人下载(然而要留神网络)。
下载和缓存反对的包管理器最新版(全局环境)
corepack prepare --all
切换到指定版本
corepack prepare pnpm@<version> --activate
在 node16.17 后,反对 latest 下载最新版本
corepack prepare pnpm@<version> --activate
应用
这一步,咱们才开始真正应用 Corepack
的能力。
咱们当初某个我的项目想只应用 pnpm,然而有时候包管理器太多,忘了进去就 yarn 或者 npm,导致产生了不同的依赖构造以及 lock 文件等等。那么请在 package.json 中增加 packageManager
字段。(packageManager 后边工具必须指定版本且如同必须指定语义化版本,即 x.y.z 模式,这就比拟坑了,我看 issis 有人提这个问题了,看看官网会不会放开)
例如:
{
"name": "test",
"version": "3.8.6",
"description": "test",
"author": "DLLCNX",
"private": true,
"packageManager": "pnpm@7.23.0",
"scripts": {
"dev": "vite",
"build:prod": "vite build",
"preview": "vite preview"
},
"dependencies": {
"pinia": "2.0.22",
"vue": "3.2.45",
"vue-cropper": "1.0.3",
"vue-router": "4.1.4"
},
"devDependencies": {}}
而后咱们在此我的项目下应用 npm 和 yarn 以及 pnpm:
yarn 和 npm 不让应用,pnpm 能够失常应用。(此处留神,npm 下面说过你须要独自开启,不然此处 npm 仍旧能够应用)
问题
1. Segmentation fault
问题:
开启 corepack enable npm
后,应用 npm 时,呈现 Segmentation fault
起因简述:
因为 corepack 版本是随着 node 版本公布的。一旦在 corepack@<=0.18.0
,而npm@>9.7.0
时,如果开启 npm 治理,就会报Segmentation fault
,如同存在不兼容。fix: disable v8-compile-cache
when using npm@>=9.7.0
by merceyz · Pull Request #276 · nodejs/corepack (github.com)
解决办法:
执行 npm install -g corepack
降级 corepack 即可,截止 2024 年 2 月,最新版是corepack@0.25.2
,反对Node v18.17.1 || >=20.10.0
。
然而:
然而我发现我本人的 Node 版本是 Node v18.12.1,我如果装置 corepack@0.25.2
,三个命令因为 node 版本和 corepack 不匹配都用不了。而corepack@0.19.0
能够应用,然而它会把 npm 链接到 10.4.0 版本。(难堪)
上一步,咱们执行降级能够解决问题,然而有一个问题。例如我是 Node v18.2.1
,其对应npm v8.19.2
。一旦我执行corepack enable npm
强行开启 npm 治理,那么我如果发现报错了,想降级 corepack
,后果因为执行不了 npm 命令,无奈降级,即便执行corepack disabled
敞开也不行,陷入了死循环。
所以
如果 Node 18 以下版本倡议还是别开启 corepack enable npm
了,太折腾了,开启 yarn 和 pnpm 即可。
如果版本是 18,倡议间接应用 18 的最新版本 Node v18.19.1。
提醒最举荐间接应用 Node 最新版,毕竟 corepack
随着版本也在更新公布。
2. node v14 开启 corepack 后应用 yarn 报版本问题
起因简述:
因为 corepack 默认装置了 yarn 和 pnpm 的最新版,而最新版 yarn 或者 pnpm 的 node 版本要求可能高于 14。
解决办法: 利用以下命令切换适宜的版本
corepack prepare yarn@x.y.z --activate # 切换数字版本
#或
corepack prepare yarn@1 --activate # 切换 1 版本
#或
corepack prepare yarn@stable --activate # 切换最新版
3. 开启 corepack 后,执行失败Internal Error
其实会去网络下载 pnpm 和 yarn,如果也开启 npm,同理睬去下载 npm,可能会因为网络下载失败。
多试几次,或者看看官网缓存策略,官网环境变量外面能够设置拜访 url 地址,然而发现国内用的淘宝镜像地址因为是重定向模式,目前无奈用。环境变量
4. 如果没网环境呢
在有网机器上,把管理器缓存导出到 tgz 文件,在没有网的环境中导入,如下:
# 导出
corepack prepare --all -o corepack.tgz
# 导入
corepack hydrate corepack.tgz
ni
咱们通过 corepack
能够限度咱们应用什么管理器,然而还能不能再不便点,这边在 corepack
的根底上举荐一个其它工具ni
ni – 应用正确的包管理工具
下面,咱们应用 corepack
以及配合在 package.josn
中增加的 packageManager
限定字段,让咱们能够在某个我的项目中指定应用哪个包管理器,一旦应用其它的就会报正告并进行执行。那么,有没有一个工具,主动去辨认我的设置,默认执行我的包管理器呢?
那么,ni 可能适宜你。它会依据你我的项目中的锁文件或者 packageManager
配置,自动识别管理工具。corepack
目前只反对 npm、pnpm 以及 yarn,而 ni 是反对后面三个根底上,还反对 bun(新的工具,认命了,覆灭吧)。
装置
npm i -g @antfu/ni
应用
ni 其实相当于利用它本人的命令替换几个包管理器对应的命令,所以如果要让它默认执行,其实相当于你要用它的代替命令。
首先,咱们要有一个的前提。ni 假设您应用锁文件(必须得有,当初新版不论 npm 还是 pnpm,还是 yarn 执行依赖加载时其实都会产生,所以除非本人刻意解决,个别不会有问题)。
在它运行之前,它将在你的我的项目目录检测你的以后包管理器(或 packageManager 字段),yarn.lock
、pnpm-lock.yaml
、package-lock.json
、bun.lockb
、packageManager
。而后默认去运行相应的包命令
那么命令都有啥?
ni
– install
ni
# npm install
# yarn install
# pnpm install
# bun install
以下面装置依赖命令为例,咱们间接在我的项目目录输出 ni 执行,它会依据本人检索到的 lock 文件或者配置,应用对应的包管理工具去执行下载,上面的命令同理。以我下面配置过 packageManager
的我的项目为例,间接执行 ni,能够看到间接应用 pnpm 开干了。
ni vite
# npm i vite
# yarn add vite
# pnpm add vite
# bun add vite
ni @types/node -D
# npm i @types/node -D
# yarn add @types/node -D
# pnpm add -D @types/node
# bun add -d @types/node
ni --frozen
# npm ci
# yarn install --frozen-lockfile (Yarn 1)
# yarn install --immutable (Yarn Berry)
# pnpm install --frozen-lockfile
# bun install --no-save
ni -g eslint
# npm i -g eslint
# yarn global add eslint (Yarn 1)
# pnpm add -g eslint
# bun add -g eslint
# 这个应用默认配置,而不是以后的工作目录检索的工具
nr
– run
nr dev --port=3000
# npm run dev -- --port=3000
# yarn run dev --port=3000
# pnpm run dev --port=3000
# bun run dev --port=3000
nr
# 交互式地抉择要运行的脚本
# supports https://www.npmjs.com/package/npm-scripts-info convention
nr -
# 从新运行最初一个命令
nlx
– download & execute
nlx vitest
# npx vitest
# yarn dlx vitest
# pnpm dlx vitest
# bunx vitest
nu
– upgrade
nu
# npm upgrade
# yarn upgrade (Yarn 1)
# yarn up (Yarn Berry)
# pnpm update
# bun update
nu -i
# (not available for npm & bun)
# yarn upgrade-interactive (Yarn 1)
# yarn up -i (Yarn Berry)
# pnpm update -i
nun
– uninstall
nun webpack
# npm uninstall webpack
# yarn remove webpack
# pnpm remove webpack
# bun remove webpack
nun -g silent
# npm uninstall -g silent
# yarn global remove silent
# pnpm remove -g silent
# bun remove -g silent
nci
– clean install
nci
# npm ci
# yarn install --frozen-lockfile
# pnpm install --frozen-lockfile
# bun install --no-save
如果不存在相应的管理器,则此命令将在此过程中全局装置它。
na
– agent alias
na
# npm
# yarn
# pnpm
# bun
na run foo
# npm run foo
# yarn run foo
# pnpm run foo
# bun run foo
问题
-
执行程序
咱们上边说了,ni 会去检测我的项目目录的 lock 文件,而后抉择应用哪个工具。然而,如果几个包管理工具锁文件都有呢?
通过验证:
- 如果
package.josn
设置了packageManager
参数,那么以其指定的工具为准。 - 如果没有
packageManager
限定工具,会从 pnpm->yarn->npm 顺次检索 lock 文件。
- 如果
相干文章
包管理工具之从 NPM 到 PNPM(https://dllcnx:18888/2024/01/81af97faf393/)
包管理工具之仓库源管理工具 nrm(https://dllcnx:18888/2021/11/a05b75568d68/)