6

速通 npm、yarn、pnpm

 1 year ago
source link: https://ssshooter.com/2023-03-03-npm-yarn-pnpm/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

速通 npm、yarn、pnpm

速通 npm、yarn、pnpm

2023-03-06coding

npm<v3

node 依赖管理器的起源,在 npm 前两个版本中,依赖无限嵌套,各种重复,被调侃质量比黑洞还大。

yarn v1

yarn,代表 Yet Another Resource Negotiator。v1 版本现在被称为 yarn classic,当年拥有不少注目特性,DX(开发体验)↑ 安全 ↑ 安装速度 ↑,创新点:

  • 依赖提升(hoisting)、依赖安装扁平化
  • 引入 lock 文件
  • 有一些 npm 没有的命令,例如更新依赖到最新版本
  • 支持 monorepo

但是引入了两个问题:

点击上面两个链接有详细解析,下面用中文总结几句。

依赖提升只能提升一个版本,其他版本依然安装在嵌套的 node_modules 中,会重复安装。所以如果项目里要求各种固定版本,依然是要安装一大堆重复的东西。

不过好消息是按照正常开发习惯和开发周期,下面这一大堆其实都只需要安装一次,以下是真实项目的 lock 文件的一部分:

lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@~4.17.0:
  version "4.17.21"
  resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==

安装了一大堆不同版本的 lodash 其实都可以使用 4.17.21,它符合所有版本要求。不确定版本要求的写法可以在 npm semver calculator 查询。

因为依赖提升这个特性,非直接依赖的包你也能直接使用,因为全都平铺在顶层 node_modules,这种可以依赖你没直接依赖的包的情况就是幽灵依赖。

以前开发一个库的时候就遇到这个问题,开发的时候默认引入了某个工具,开发时一切正常,但是打包出来别人用的时候缺了一个依赖。

npm>=v3

npm3 之后的版本向 yarn 学习:

  • 跟进了 hoisting
  • 跟进了 lock 文件

How npm3 Works 比较详细地解析了 npm3 的改进。

然而……该有的问题还是没解决。

pnpm 使用软硬链接的巧妙结合同时解决以上两个问题。

  • 所有依赖有一个全局仓库,被引用的会硬链(hard link)到项目
  • 对于依赖之间的关系,使用软链(Symlink)链接,实现最短路径查询依赖

官网给出这样的例子:

node_modules
├── foo -> ./.pnpm/[email protected]/node_modules/foo
└── .pnpm
    ├── [email protected]
    │   └── node_modules
    │       ├── bar -> <store>/bar
    │       └── qar -> ../../[email protected]/node_modules/qar
    ├── [email protected]
    │   └── node_modules
    │       ├── foo -> <store>/foo
    │       ├── bar -> ../../[email protected]/node_modules/bar
    │       └── qar -> ../../[email protected]/node_modules/qar
    └── [email protected]
        └── node_modules
            └── qar -> <store>/qar

<store>/ 的是硬,带 ../../ 的是软。即使依赖深度是 foo > bar > qar 依然可以保持这样的浅层结构。顶层只有一个 foo,没有幽灵依赖,项目用到的版本都在 .pnpm 平铺,不会造成依赖分身。

yarn>=v2

可以使用激进的 Plug’n’Play (PnP)

Yarn generates a single .pnp.cjs file instead of the usual node_modules folder containing copies of various packages.

PnP 不用 node.js 自己去找依赖位置了,直接用 .pnp.cjs 告诉它所有依赖的准确位置,这个准确位置是一个中央仓库,所以也不需要把依赖复制到项目的 node_modules 里。PnP 出现之初有很多工具都不支持这种依赖安装方法,现在兼容性估计好很多了。但是只要 pnpm 的速度还能接受,个人认为还是直接用传统 node_modules 吧。

很惊讶,根据 JavaScript package managers compared: npm, Yarn, or pnpm? 中的性能测试结果,npm v8.1.2 已经比 yarn v1.23.0 快了,首次安装的速度 pnpm 仍然拉开两位前辈一大截。打破常规的 PnP 自然是最快的,但是要在项目中使用它,还得看项目能不能兼容 PnP。(虽然 pnpm 的软硬链有些包也不支持)

npm,yarn,pnpm performance

暂时没有留言,要抢沙发吗?


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK