大家好,这里是大家的林语冰。
本期共享的是 ------ npm
vs yarn
vs pnpm
的异同点和优缺点。
2024 年标志着 Node 生态系统的关键时刻,开发者在为项目选择合适的包管理器时面临着不同的选择。npm
、yarn
和 pnpm
脱颖而出,成为领头羊,因为它们在 Node 生态系统中使用最广泛。每个软件包都提供独特的特性和功能,旨在直面现代开发环境的挑战。
我们将深度学习它们之间的异同点和优缺点,辅助开发者就哪种工具最适合您的项目需求做出机智的选择,并深入了解影响其在 2024 年使用的不断发展的趋势。
免责声明
本文属于是语冰的直男翻译了属于是,略有删改,仅供粉丝参考。英文原味版请传送 Choosing the Right Node.js Package Manager in 2024: A Comparative Guide。
npm
:Node 包管理器
npm
是 Node 的默认包管理器,以其广泛的包注册表以及与 Node 生态系统的无缝集成而闻名。npm
的诞生是为了简化 Node 项目中安装、管理和共享代码依赖的过程。npm
提供了包含超过 200
万个软件包的庞大存储库,使其成为 JS 爱好者的综合生态系统和地球上最大的软件注册表。
npm
的优势
- 庞大的包存储库 :开发者因为
npm
无与伦比的包注册表而青睐它,它拥有超过200
万个包,涵盖广泛的功能和用例。开发者可以访问丰富的开源库和模块生态系统,使它们能够利用现有解决方案,并加速开发。 - Node 的默认选择 :
npm
与 Node 安装"捆绑营销",使其成为 Node 项目的默认包管理器。npm
与 Node 生态系统的无缝集成简化了依赖管理,并确保与 Node 运行时的兼容性。 - 成熟的生态系统 :
npm
拥有成熟且完善的生态系统,具有强大的基础设施和社区支持。npm
已经使用多年,并与时俱进,成为管理项目依赖关系稳定可靠的工具人。 - 全面的 CLI :
npm
提供了全面的 CLI(命令行界面),其中包含用于管理包、脚本和配置的各种命令和选项。开发者可以使用npm
直观的 CLI 轻松执行安装、更新、发布和编写脚本等任务。 - 语义版本控制 :
npm
遵循 SemVer(语义版本控制)规则,允许开发者准确指定依赖的版本范围。这可以确保更新包时的兼容性和可预测性,从而最大限度地降低项目中发生破坏性更新的风险。 - 自定义脚本 :
npm
允许开发者在package.json
文件中定义自定义脚本,这可以使用npm run
命令执行。此功能可以实现构建、测试和部署等各种开发任务的自动化,从而简化开发工作流程。 - 与
npm
注册表集成 :npm
与npm
注册表无缝集成,npm
注册表是一个中心化存储库,开发者可以在其中发布和发现软件包。这种中心化基建促进了 JS 社区内的协作和代码共享,为生态系统的增长和创新做出了贡献。
总体而言,npm
提供了一个强大且功能丰富的包管理解决方案,可以满足开发者构建 Node App 的需求。npm
广泛的包存储库、成熟的生态系统、全面的 CLI 和社区支持使其成为全球 JS 开发者的首选。
npm
的缺陷
- 性能问题 :
npm
有时会遭遇性能问题,尤其是在具有许多依赖的大型项目中。某些开发者发现Yarn
和pnpm
更快。安装时间慢和资源消耗高可能会影响开发者的工作效率和构建时间。 - 版本控制复杂性 :使用
npm
管理包版本和依赖冲突可能具有挑战性,特别是在具有复杂依赖树的项目中。解决版本冲突并确保包之间的兼容性可能需要手动干预和仔细监督。 - 依赖膨胀 :
npm
在本地安装包的默认行为可能会导致依赖膨胀(dependency bloat),即项目随着时间的推移积累不必要的依赖。这可能会增加项目规模和复杂性,并可能影响性能和维护工作。 - 安全问题 :
npm
包无法避免安全漏洞,并且依赖第三方代码会给项目带来潜在风险。虽然npm
提供了用于审核包和检测漏洞的工具,但开发者必须保持警惕并积极主动地解决安全问题。 - 依赖中心化注册表 :
npm
依赖中心化注册表来进行软件包分发和搜索,从而引入了单点故障和潜在的网络瓶颈。npm
注册表中的干扰或中断可能会扰乱开发工作流程和依赖管理流程。 - 有限的离线支持 :虽然
npm
通过本地缓存提供了某些离线安装支持,但其离线功能不如Yarn
等其他包管理器强大。在互联网连接有限或间歇性的环境中工作的开发者在依赖npm
时可能会"骑猫难下"。
总体而言,虽然 npm
是一个强大且广泛采用的包管理器,但开发者应该意识到 npm
的局限性,并考虑替代解决方案或最佳实践,从而减轻依赖管理和项目维护方面的潜在挑战。
yarn
yarn
是 Node 的包管理器之一,由脸书开发。yarn
的诞生是为了解决 npm
遭遇的某些限制和性能问题,重点关注性能、可靠性和确定性依赖解决方案。
yarn
的优势
- 性能优化 :与
npm
相比,yarn
以其更快的安装时间和更高效的依赖关系解析而闻名。它通过并行包安装和缓存机制来实现这一点,从而减少管理依赖所需的时间和资源。 - 确定性依赖解析 :
yarn
通过生成一个锁定文件yarn.lock
,来捕获项目中所用依赖的确切版本,从而确保确定性依赖项解析。这有助于防止依赖冲突,并确保不同开发环境之间的一致性。 - 离线支持 :
yarn
为离线安装提供强大的支持,使其适合互联网连接有限或间歇性的环境。它在本地缓存软件包,允许开发者在不依赖活动互联网连接的情况下安装依赖。 - 直观的 CLI :
yarn
提供直观的 CLI(命令行界面),其中包含用于管理包和运行脚本的清晰简洁的命令。其 CLI 设计为用户友好且易于使用,简化了开发工作流程。 - 改进的错误处理 :
yarn
提供详细的错误消息和诊断,使开发者可以更轻松地排除和解决与包安装或依赖管理相关的问题。 - 向后兼容性 :
yarn
保持与npm
注册表和现有npm
工作流程的兼容性,允许开发者从npm
无缝过渡到yarn
,而不会扰乱它们的项目。
总体而言,yarn
是一个强大且高效的 Node 包管理器,提供性能改进、确定性依赖解析、离线支持和直观的 CLI。yarn
在 Node 社区中得到了广泛采用,并广泛用于大小型项目。
yarn
的缺陷
- 兼容性问题 :尽管
yarn
的目标是与npm
兼容,但两个包管理器之间仍然可能偶尔会出现兼容性问题或行为差异。在npm
和yarn
之间迁移项目时,这有时会导致意外行为或困难。 - 资源消耗 :
yarn
的缓存机制和并行安装过程会消耗大量系统资源,尤其是在具有大型依赖树的项目中。这可能会影响开发环境的性能,特别是在资源有限或硬件较旧的系统上。 - 社区碎片化 :虽然
yarn
在 Node 社区中得到了广泛采用,但其生态系统和社区支持可能仍然比npm
更小、更广泛。与npm
相比,这可能会导致第三方插件、集成和社区驱动的措施更少。 - 锁定文件漂移的可能性 :
yarn
生成锁定文件yarn.lock
,确保确定性的依赖关系解析。虽然但是,如果开发者手动修改依赖或更新包,而不更新锁定文件,那可能会导致锁定文件漂移(lockfile drift),即锁定文件与项目中安装的实际依赖不同步。 - 有限的配置选项 :与
npm
相比,yarn
的配置选项更加有限,npm
可以对包安装、注册表设置和依赖管理的其他方面提供更精细的控制。yarn
爱好者可能会发现自己缺乏npm
中可用的某些自定义选项。 - 维护开销 :虽然
yarn
提供了性能优化和依赖解析等优点,但它在管理特定于yarn
的配置、锁定文件和依赖方面也带来了额外的维护开销。这会增加项目维护和版本控制的复杂性。
总体而言,虽然 yarn
解决了 npm
的许多缺陷,并在性能和可靠性方面提供了显着改进,但开发者在决定是否在其项目中采用 yarn
时,必须考虑权衡和潜在的缺点。
pnpm
pnpm
是"Performant npm"(高性能 npm
)的缩写,是 Node App 的包管理器。与 npm
和 yarn
等传统包管理器不同,pnpm
采用独特的依赖关系管理方法,强调效率、磁盘空间优化和安装速度。
pnpm
的优势
- 共享依赖关系 :
pnpm
使用共享依赖关系模型,其中跨项目的公共依赖关系存储在磁盘上的单一位置。这种方案通过避免依赖的重复副本,最大限度地减少磁盘空间的使用,从而显著节省存储资源。 - 高效安装 :通过利用共享依赖和高效缓存机制,与传统包管理器相比,
pnpm
提供更快的安装时间。pnpm
可以大大减少安装依赖所需的时间,尤其是在具有大型依赖树的项目中。 - 确定性依赖解析 :与
yarn
类似,pnpm
通过生成锁定文件pnpm-lock.yaml
,捕获项目中使用的依赖的确切版本,从而确保确定性依赖解析。这有助于防止依赖冲突,并确保不同开发环境之间的一致性。 - 减少网络带宽 :
pnpm
通过跨项目共享包下载来优化网络带宽使用。当多个项目需要相同的依赖时,pnpm
只获取一次软件包,并在所有项目之间共享它,从而减少通过网络传输的数据量。 - 提高缓存效率 :
pnpm
的缓存机制设计得十分高效,这减少了重新下载软件包的需要,并提高了安装速度。pnpm
维护软件包和依赖的中心化缓存,从而实现更快的安装,并最大限度地减少冗余下载。 - CLI(命令行界面) :
pnpm
提供直观的 CLI,其中包含用于安装、更新和管理软件包的命令。其 CLI 设计为用户友好且易于使用,具有用于执行常见任务的清晰简洁的语法。 - 与
npm
的兼容性 :pnpm
保持与npm
注册表和现有npm
工作流程的兼容性,使开发者可以轻松地从npm
过渡到pnpm
,而不干扰它们的项目。pnpm
可以从npm
注册表安装软件包,并与现有的npm
软件包和配置无缝协作。
总体而言,pnpm
在磁盘空间优化、安装速度和网络带宽使用方面提供了显著的优势,使其成为期望简化 Node 项目中依赖管理的开发者有吸引力的选择。pnpm
的共享依赖模型和高效的缓存机制使其十分适合具有大型依赖和资源限制的项目。
pnpm
的缺陷
- 学习曲线 :从
npm
和yarn
等传统包管理器切换到pnpm
可能需要开发者学习pnpm
特定的新命令、工作流程和概念。虽然pnpm
的 CLI 很直观,但仍然存在学习曲线,尤其是对于不熟悉其共享依赖模型和缓存机制的开发者而言。 - 兼容性问题 :尽管
pnpm
的目标是与npm
和yarn
兼容,但包管理器之间仍然可能偶尔会出现兼容性问题或行为差异。在npm/yarn
和pnpm
之间迁移项目时,这有时会导致意外行为或困难。 - 资源消耗 :虽然
pnpm
的共享依赖模型减少了磁盘空间的使用,但它仍然可能消耗大量的系统资源,尤其是在具有大型依赖的项目中。缓存依赖项和管理共享包可能需要额外的内存和处理能力,从而影响开发环境的性能。 - 锁定文件处理 :
pnpm
生成一个锁定文件 pnpm-lock.yaml,确保确定性的依赖关系解析。虽然但是,管理锁定文件并确保其在不同环境中的一致性可能具有挑战性。开发者必须小心避免锁定文件漂移(lockfile drift),即锁定文件与项目中安装的实际依赖项不同步。 - 社区支持 :虽然
pnpm
已在 Node 社区中得到采用,但其生态系统和社区支持可能仍然比npm
和yarn
更小、更广泛。这可能会导致第三方插件、集成减少,可用文档资源和教程以及社区驱动的计划减少,从而限制了pnpm
用户的可用资源和支持。
总体而言,虽然 pnpm
在磁盘空间优化和安装速度方面提供了令人瞩目的优势,但开发者在决定是否在其项目中采用 pnpm
时,应仔细权衡利弊并考虑潜在缺陷。
项目结构
npm
:使用 npm install
时,会创建 package-lock.json
,并生成 node_modules
文件夹。我们可以手动将 .npmrc
配置文件放置在根级别。
yarn
:类似地,yarn
会生成一个 yarn.lock
文件和一个 node_modules
文件夹。我们还可以使用 .yarnrc
文件配置 yarn
;yarn
也认可 .npmrc
文件。
npm
和 yarn
方法的一个问题是软件包被复制多次,来满足多个依赖。pnpm
搞定了这个问题,没有压平依赖树。每个包的依赖都分组在一个 node_modules
文件夹中,并且使用符号链接将依赖项分组在一起,因此目录树是扁平的。
pnpm
:相比之下,pnpm
有所不同,并且不会创建扁平的依赖关系树。使用 pnpm i
安装依赖项后,会在 node_modules
文件夹旁边生成一个 package.json
文件。虽然但是,由于 pnpm
的内容可寻址存储方法,node_modules
目录的结构与 npm
和 yarn
的结构截然不同。
零和博弈
最终,最适合您的项目的包管理器取决于您的具体要求、偏好以及适应新工作流程的意愿。实验和仔细考虑所涉及的权衡,这会辅助您做出符合项目目标和限制的明智决策。
根据上文提及的某些优缺点,某些进一步的研究和个人意见,我们可以瞄一眼下面的对比图,数字 1 表示最低分数,数字 3 表示最高分数:
尽管 npm
和 yarn
人气更高,但 pnpm
似乎有一个光明的未来。我们瞄一下 JS 包管理器的某些基准测试:
- 速度 :
pnpm
比npm
快3
倍,效率更高,并且具有冷热缓存,pnpm
比yarn
更快。
- 安全性 :
pnpm
与yarn
一样,有一个特殊文件,其中包含所有已安装软件包的校验和。这确保了所有已安装包在代码执行之前的完整性。关于npm
,由于npm
处理坏包的方式,出现了某些安全漏洞,直接影响了许多项目。 - 磁盘空间效率 :
pnpm
采用内容可寻址文件系统在磁盘上存储包和依赖。这意味着相同的包不会重复。即使同一包的不同版本,pnpm
也能智能地最大化代码重用。举个栗子,如果某个包的版本 1 由 500 个文件组成,而版本 2 仅添加了一个文件,那么pnpm
不会为版本 2 复制原始 500 个文件。相反,它会建立一个到现有 500 个文件的硬链接,并且只写入新文件。相比之下,npm
会复制版本 2 的原始 500 个文件。这种区别在大型 monorepo 项目中兹事体大,其中一个包被许多其他项目使用,在使用pnpm
时可能会节省大量磁盘空间。 - 锁定文件:
yarn
生成一个yarn.lock
文件,确保所有团队成员都使用相同的软件包版本。这有助于防止"我的机器听我的"的问题。与yarn
一样,pnpm
使用pnpm-lock.yaml
文件,确保依赖版本一致。npm
可能会在package-lock.json
中出现不一致的情况,这可能会令人头大,并给开发者带来问题。
本期话题是 ------ 你更常用或青睐哪个包管理器,以及为什么?
欢迎在本文下方自由言论,文明共享。谢谢大家的点赞,掰掰~
《前端猫猫教》每日 9 点半更新,坚持阅读,自律打卡,每天一次,进步一点。