npm、yarn、pnpm有什么区别?有什么优缺点?

1、前言

相信大家对这三个包管理器都不陌生,但是总有些疑惑,已经有了npm,为什么还要出现yarnpnpm,有些人不了解,而有些人是模凌两可的知晓一些,接下来我用最直观的包安装方式,这里我通过安装express来详解

2、Npm

对于npm这里需要区分2.x版本,以及2.x版本以上的,因为这两者在2.x以下版本,npm安装包方式是以嵌套方式安装的包,而2.x版本以上则是平铺方式安装。

2-1、Npm@2.x

image.png

这是环境:node: 4.9.1、npm: 2.15.12
我们开始安装express
image.png

也就是说 npm2 的 node_modules 是嵌套的。

这很正常呀?有什么不对么?

这样其实是有问题的,多个包之间难免会有公共的依赖,这样嵌套的话,同样的依赖会复制很多次,会占据比较大的磁盘空间。

这个还不是最大的问题,致命问题是 windows 的文件路径最长是 260 多个字符,这样嵌套是会超过 windows 路径的长度限制的。

当时npm 还没解决,社区就出来新的解决方案了,就是 yarn

3-1、yarn & npm > 3.x

yarn 是怎么解决依赖重复很多次,嵌套路径过长的问题的呢?

铺平。所有的依赖不再一层层嵌套了,而是全部在同一层,这样也就没有依赖重复多次的问题了,也就没有路径过长的问题了。

image.png

但是有些包还是有嵌套问题的,为什么还会有嵌套问题呢?
假设现在我们项目依赖body-parser@1.19.1,且依赖express
那我们删掉之前测试的node_modules,重新安装:

npm i express body-parser@1.19.1 -S

image.png

发现没有?在express中又出现了嵌套问题了

因为一个包是可能有多个版本的,提升只能提升一个,所以后面再遇到相同包的不同版本,依然还是用嵌套的方式。

yarnnpm@3.x 都采用了铺平的方案,这种方案就没有问题了么?

并不是,扁平化的方案也有相应的问题。

最主要的一个问题是幽灵依赖

而且还有一个问题,就是上面提到的依赖包有多个版本的时候,只会提升一个,那其余版本的包不还是复制了很多次么,依然有浪费磁盘空间的问题。

那社区有没有解决这俩问题的思路呢?

当然有,这不是 pnpm 就出来了嘛。

那 pnpm 是怎么解决这俩问题的呢?

3-2、幽灵依赖

什么是幽灵依赖?
也就是你明明没有声明在 dependencies 里的依赖,但在代码里却可以 require 进来。

假设我们的项目只有一个依赖express

const BodyParser = require('body-parser');
console.log(BodyParser);

我们发现代码可以 正常运行,因为在express中他依赖了body-parser而因为平铺的方式,我们可以直接引入这个包,但是这个是很大的问题!!!
在假设后期项目中不需要依赖express,我们直接卸载了express,但是我们代码中引了body-parser,那么就存在了问题.

幽灵依赖可能会导致以下问题:

  • 项目在不同的环境下表现不一致,因为安装的依赖项版本不同。

  • 可能会安装未经测试的、低质量的或包含漏洞的软件包。

  • 项目构建和部署过程可能会因为依赖项版本不兼容而失败。

4、pnpm

回想下 npm3yarn 为什么要做node_modules扁平化?不就是因为同样的依赖会复制多次,并且路径过长在 windows 下有问题么?

那如果不复制呢,比如通过link

首先介绍下 link,也就是软硬连接,这是操作系统提供的机制,硬连接就是同一个文件的不同引用,而软链接是新建一个文件,文件内容指向另一个路径。当然,这俩链接使用起来是差不多的。

如果不复制文件,只在全局仓库保存一份 npm 包的内容,其余的地方都 link 过去呢?

这样不会有复制多次的磁盘空间浪费,而且也不会有路径过长的问题。因为路径过长的限制本质上是不能有太深的目录层级,现在都是各个位置的目录的link,并不是同一个目录,所以也不会有长度限制。

没错,pnpm 就是通过这种思路来实现的。

image.png

包是从全局 store 硬连接到虚拟 store 的,这里的虚拟 store 就是 node_modules/.pnpm。

并且确实不是扁平化的了,依赖了 express,那 node_modules 下就只有 express,没有幽灵依赖。

查看.pnpm

image.png

所有的依赖都在这里铺平了,都是从全局 store 硬连接过来的,然后包和包之间的依赖关系是通过软链接组织的。

也就是说,所有的依赖都是从全局 store 硬连接到了 node_modules/.pnpm 下,然后之间通过软链接来相互依赖。

官方的原理图


image.png

这就是 pnpm 的实现原理。

那么回过头来看一下,pnpm 为什么优秀呢?

首先,最大的优点是节省磁盘空间呀,一个包全局只保存一份,剩下的都是软硬连接,这得节省多少磁盘空间呀。

其次就是快,因为通过链接的方式而不是复制,自然会快。

4-1、如果修改pnpm项目中一个包依赖的源码,有什么影响?为什么?

假设想在有两个项目:《pnpm-obj-1》、《pnpm-obj-2》,其中这两个项目都是用pnpm安装了React最新版本,但如果我修改了其中 "pnpm-obj-1" react的源码,会有什么影响么?

我们实际操作下:

image.png

接下来我们只更改pnpm-test-1中的react源码
修改源码

然后在查看pnpm-test项目中react源码

pnpm-test

总结:

然后我们发现如果在其中一个项目修改依赖包源码,发现其余相同依赖的包也会被修改!!!这是为什么?因为pnpm中的包依赖是通过全局缓存硬连接至项目的。所以当你修改其中一个包源码,会影响其他项目的包,所以使用pnpm包慎重修改包的源码!!!

通过这个案例,又延伸一个问题,这样修改包源码,会影响新的项目新安装相同的依赖么?

4-2、修改旧项目包源码,会影响新项目包的源码么?

我们直接说结果,是不会影响的。那有人在问,上诉我们修改旧项目的源文件,因为硬连接的原因,也就是相当于修改了pnpm全局store的中的源文件包,而,pnpm新安装包是检测全局store有没有这个包,如果有那么直接硬连接过来,而达到快速的安装包,那为什么新安装的包不会受到影响?

总结

pnpm 最近经常会听到,可以说是爆火。本文我们梳理了下它爆火的原因:

npm2 是通过嵌套的方式管理 node_modules 的,会有同样的依赖复制多次的问题。

npm3+ 和 yarn 是通过铺平的扁平化的方式来管理 node_modules,解决了嵌套方式的部分问题,但是引入了幽灵依赖的问题,并且同名的包只会提升一个版本的,其余的版本依然会复制多次。

pnpm 则是用了另一种方式,不再是复制了,而是都从全局 store 硬连接到 node_modules/.pnpm,然后之间通过软链接来组织依赖关系。

这样不但节省磁盘空间,也没有幽灵依赖问题,安装速度还快,从机制上来说完胜 npm 和 yarn。

pnpm 就是凭借这个对 npm 和 yarn 降维打击的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,440评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,814评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,427评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,710评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,625评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,014评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,511评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,162评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,311评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,262评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,278评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,989评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,583评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,664评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,904评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,274评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,856评论 2 339

推荐阅读更多精彩内容