Hi! 这里是疑惑中的前端JustHappy写的技术博客,不知道大家有没有同样的疑惑,npm、Yarn、 pnpm这些软件包管理的东西该如何选择?看心情吗?还是看天气?或许这篇文章可以解决我们的疑惑
npm 前端“建材市场”
-
特点:npm是Node.js默认的包管理工具,拥有广泛的支持和活跃的社区,因此可以轻松地找到并安装大多数前端依赖项。npm不仅是一个软件包下载、管理工具,更是前端的“建材市场”,不管是yarn、pnpm都要来她的平台进货
-
优点:
- 广泛支持:作为Node.js的默认包管理工具,几乎所有的Node.js库和框架都支持npm。
- 官方工具:npm是Node.js官方的工具,因此兼容性和生态系统非常广泛,而且会跟随Node.js下载,不必单独安装。
- 功能丰富:npm提供了大量的命令选项,可以处理安装、发布、发布版本、管理依赖等任务。
- 生态地位:npm不只是一个Node.js软件包下载工具那么简单,经过十余年的发展,npm已经是世界上软件包数量最多的平台(感觉这种上游生态位的建设是软件国产化替代中最难的,马太效应,强者恒强)
-
缺点:
- 速度较慢(国内是真的很慢):相比yarn和pnpm的“并行下载”,npm是默认“串行下载”,安装速度较慢。
npm1.x(古早版本)只支持串行下载,npm2.x之后开始支持并行下载但是默认还是串行安装的 - 磁盘空间浪费:npm安装依赖时会在项目中存储每个依赖包的副本,这会导致磁盘空间的浪费。
- 依赖管理较差:npm曾有一个较为松散的依赖管理机制,容易导致“幽灵依赖”和版本冲突问题。
- 速度较慢(国内是真的很慢):相比yarn和pnpm的“并行下载”,npm是默认“串行下载”,安装速度较慢。
幽灵依赖(Phantom Dependencies)是指那些在项目的
package.json文件中没有直接声明,但却能够在项目的依赖树中找到并使用的模块,其出现的原因是由于npm的扁平化包管理,具体是什么样子的呢?打个比方你安装了一个包比如说Element,为了“支持”Element,又要依据node_module文件夹下的Element的package.json安装一些npm包,而你并没有在你自己项目的package.json中声明了这里面的某些包,但是你却可以调用到,具体这个我们在下面详细说说
如何弥补这些npm缺点呢?
速度慢
-
使用并行下载:如果你不想使用其他的包管理器下载可以尝试使用npm 的 --parallel 选项
-
切换国内镜像:
# 在下载时配置
npm install --registry=https://registry.npmmirror.com
#在全局配置
npm config set registry https://registry.npmmirror.com
你也可以直接使用cnpm来安装
幽灵依赖 and 版本冲突
这个目前是只有pnpm解决了幽灵依赖这个问题,我们会在下面讲pnpm的时候详细说说
先来说说幽灵依赖是怎么来的吧......
早期的npm其实是没有这个问题的,哪个时候软件包安装依赖时遵循树状结构,就是安装一个包会在其文件夹内部的node_module中安装当前这个包的依赖,就像下面这样。在这种情况下你自然调用不了在自己项目根目录下没有声明的。
但是在npm3.x版本之后,npm采用扁平化的安装策略,即所有软件依赖都安装在同一级的node_module下,就像下面这幅这样,这其实是有一下子的好处的
- 减少重复依赖
- 提高安装速度
- 解决依赖路径过长的问题
但这也带来了幽灵依赖 以及 版本冲突 等问题
Yarn “大厂开发的”
-
特点:Yarn是由Facebook开发的JavaScript包管理工具,旨在解决npm在性能和依赖管理上的不足。
-
优点:
- 安装速度快:Yarn通过并行化依赖包的下载和缓存机制大大提升了安装速度。
- 离线缓存:Yarn会将所有安装的依赖包缓存在本地,确保下次安装时可以快速离线安装。
- 稳定的依赖树:Yarn默认使用yarn.lock文件来锁定依赖版本,确保每次安装的依赖版本一致。
-
缺点:
- 社区支持不如npm:尽管Yarn受到了广泛的欢迎,但仍然有部分社区和工具的支持不如npm。
- 安装配置复杂:对于一些用户来说,Yarn需要单独配置,尤其是工作区的设置可能让新手感觉有些复杂。
- 同样存在“幽灵依赖”问题
pnpm “又快又稳又省的幽灵杀手” 🔪
- 特点:pnpm是相对较新的包管理工具,它的设计理念主要关注性能、磁盘空间使用效率和更严密的依赖管理。
从npm周下载量可以看到这个项目目前还是受很多人喜欢的
-
优点:
- 有效的磁盘使用:pnpm使用了共享的存储策略,来存储所有项目的所有包版本以及每个项目所需的符号链接,显著减少磁盘空间的使用。
- 更严格的依赖关系解析:pnpm不会让你的包访问那些没有被明确列为其依赖的包,这使得依赖关系更清晰。
-
缺点:
- 兼容性问题:由于pnpm的依赖关系解析方式更严格,某些包可能会在pnpm下运行不正常,尽管在npm或Yarn下可以正常运行。
- 手动维护依赖:pnpm为了避免幽灵依赖的存在,要求所有的依赖都需要在package.json文件中显式声明,随着依赖项的增多,维护难度也会增加。
pnpm是如何解决“幽灵依赖”的 👻
上面介绍npm的时候说到了npm和yarn为了提高安装速度和减少重复依赖选择了使用扁平化的node_module结构,但是这带来了“幽灵依赖”和版本冲突问题,但是pnpm不做选择,它全都要,这点开pnpm的官方文档就能看到他们项目的初衷
对于”幽灵依赖“,pnpm对症下药,既然是因为扁平化,那我就不使用扁平化不就行了!好的,那么问题来到如何使得非扁平化的node_module具有比肩甚至超越扁平化node_module的性能呢?(也就是节约磁盘空间和提高安装速度)
创建一个非扁平的 node_modules 这是pnpm中文网的链接大家也可以去这里看
cnpm “建材市场”国内“总代理” 👨🏻💻
-
特点:cnpm(China npm)是阿里巴巴开发的一款包管理工具又叫做“淘宝镜像”,主要用于解决国内开发者使用npm时的网络问题。cnpm的操作命令基本上和npm一样,是国内npm的“等效替代",其实这才是最推荐国内初学者使用的包管理,稳定,速度不慢
-
优点:
- 国内镜像:cnpm使用国内镜像源,解决国内网络访问npm慢的问题。
- 与npm兼容:cnpm的命令与npm基本兼容,使用起来非常方便。
-
缺点:
- 需要额外安装:与npm相比,生态系统和社区相对较小。
- 事实上就是一个换了国内镜像的npm,也就是说npm的缺点他都有
值得注意的是cnpm换过一次镜像地址
Bun “我要开个新超市” 🏘️
-
特点:Bun是用Zig开发的JavaScript运行时,非常快,并且能够保障与Node.js API的兼容性。换句话说,这不只是包软件包管理工具,而是一个完整的JavaScript运行环境,对标的是Node.js而不是单单npm
-
优点:
- 兼容Node.js:Bun被设计成可以直接适用于现有的Node.js代码库。
- 性能:执行JavaScript比Node.js更快,提升高达4倍。
- Web标准:Bun实现了最广泛采用的Web标准API,例如Fetch API和WebSocket API。
-
缺点:
- Windows支持不尽如人意,不如Linux/MacOS。
So?我*** 到底要用哪个?💢💢
我觉得应该分不同场景看待这个问题,如果是个人平时练习的话,其实大可以“看心情”,拍脑瓜子,这个不行用那个,因为个人项目的复杂度一般都不高,但是上升到团队项目就要考虑多一些,结合不同项目的特点
以下是个人的一些看法和建议吧,也是总结,不是很严谨😊
-
如果您是初学者或习惯使用npm或者cnpm:
- 对于新手来说,我们真的需要切实掌握npm,但是在国内cnpm是最稳定没有网络问题的,会在初期学习的时候节约大量的时间,也不会搞心态,真的会提升学习效率
-
如果您需要更快的安装速度:
- Yarn提供了比npm更快的安装速度,特别是在大型项目中,Yarn的并行安装技术可以显著提升性能。Yarn还提供了yarn.lock文件来确保依赖项版本的一致性。
-
如果您的项目非常大,依赖包非常多,怕出错:
- pnpm通过硬链接技术共享依赖包,减少了磁盘空间的浪费,并提供了快速的安装速度。pnpm强制依赖树的完整性,避免了“幽灵依赖”问题。
-
如果您追求更高的性能和一体化的工具包,或者想尝试新鲜事物:
- Bun是一个新兴的运行时和工具包,提供了打包、包管理、测试等功能,并且性能较高。但需要注意的是,Bun的社区支持相对较少,如果您严重依赖社区支持,可能需要考虑这一点。
OK!我们下次再见... 这里是JustHappy,如果您有任何问题,欢迎评论区留言,也欢迎点赞和收藏哦🙏🙏
或许下一篇我们可以深扒一下pnpm