npm和yarn的区别和对比

最近在学习得过程中接触到了yarn , 是一个包管理工具,用来替代npm . 下面来总结一下:

yarn有以下3个优点 :

安装速度快 (服务器速度快 , 并且是并行下载)
版本锁定
缓存机制
Yarn语法

npm init                                              ---- yarn init
npm install                                         ---- yarn 
npm install xxx@1.1.1 -g                   ---- yarn global add xxx@1.1.1
npm install xxx@1.1.1 --save            ---- yarn add xxx@1.1.1
npm install xxx@1.1.1 --save-dev     ---- yarn add xxx@1.1.1 --dev
npm uninstall xxx --save(-dev)          ----yarn remove xxx
npm run xxx                                      ---- yarn run xxxx

安装方式: npm install yarn -g

官网: https://yarn.bootcss.com/

以下内容请参考原文:https://blog.youkuaiyun.com/qiansg123/article/details/80129453
NPM
npm是Node.js能够如此成功的主要原因之一。npm团队做了很多的工作,以确保npm保持向后兼容,并在不同的环境中保持一致。

npm是围绕着语义版本控制(semver)的思想而设计的,下面是从他们的网站摘抄过来的:

给定一个版本号:主版本号.次版本号.补丁版本号, 以下这三种情况需要增加相应的版本号:

主版本号: 当API发生改变,并与之前的版本不兼容的时候
次版本号: 当增加了功能,但是向后兼容的时候
补丁版本号: 当做了向后兼容的缺陷修复的时候
npm使用一个名为package.json的文件,用户可以通过npm install --save命令把项目里所有的依赖项保存在这个文件里。

例如,运行npm install --save lodash会将以下几行添加到package.json文件中。

"dependencies": {
    "lodash": "^4.17.4"
}
请注意,在版本号lodash之前有个^字符。这个字符告诉npm,安装主版本等于4的任意一个版本即可。所以如果我现在运行npm进行安装,npm将安装lodash的主版本为4的最新版,可能是 lodash@4.25.5(@是npm约定用来确定包名的指定版本的)。你可以在此处查看所有支持的字符:https://docs.npmjs.com/misc/semver。

理论上,次版本号的变化并不会影响向后兼容性。因此,安装最新版的依赖库应该是能正常工作的,而且能引入自4.17.4版本以后的重要错误和安全方面的修复。

但是,另一方面,即使不同的开发人员使用了相同的package.json文件,在他们自己的机器上也可能会安装同一个库的不同种版本,这样就会存在潜在的难以调试的错误和“在我的电脑上…”的情形。

大多数npm库都严重依赖于其他npm库,这会导致嵌套依赖关系,并增加无法匹配相应版本的几率。

虽然可以通过npm config set save-exact true命令关闭在版本号前面使用^的默认行为,但这个只会影响顶级依赖关系。由于每个依赖的库都有自己的package.json文件,而在它们自己的依赖关系前面可能会有^符号,所以无法通过package.json文件为嵌套依赖的内容提供保证。

为了解决这个问题,npm提供了shrinkwrap命令。此命令将生成一个npm-shrinkwrap.json文件,为所有库和所有嵌套依赖的库记录确切的版本。

然而,即使存在npm-shrinkwrap.json这个文件,npm也只会锁定库的版本,而不是库的内容。即便npm现在也能阻止用户多次重复发布库的同一版本,但是npm管理员仍然具有强制更新某些库的权力。

这是引用自shrinkwrap文档的内容:

如果你希望锁定包中的特定字节,比如是为了保证能正确地重新部署或构建,那么你应该在源代码控制中检查依赖关系,或者采取一些其他的机制来校验内容,而不是靠校验版本。

npm 2会安装每一个包所依赖的所有依赖项。如果我们有这么一个项目,它依赖项目A,项目A依赖项目B,项目B依赖项目C,那么依赖树将如下所示:

node_modules
- package-A
-- node_modules
--- package-B
----- node_modules
------ package-C
-------- some-really-really-really-long-file-name-in-package-c.js


这个结构可能会很长。这对于基于Unix的操作系统来说只不过是一个小烦恼,但对于Windows来说却是个破坏性的东西,因为有很多程序无法处理超过260个字符的文件路径名。

npm 3采用了扁平依赖关系树来解决这个问题,所以我们的3个项目结构现在看起来如下所示:

node_modules
- package-A
- package-B
- package-C
-- some-file-name-in-package-c.js

这样,一个原来很长的文件路径名就从./node_modules/package-A/node_modules/package-B/node-modules/some-file-name-in-package-c.js变成了/node_modules/some-file-name-in-package-c.js。

你可以在这里阅读到更多有关NPM 3依赖解析的工作原理。https://docs.npmjs.com/how-npm-works/npm3

这种方法的缺点是,npm必须首先遍历所有的项目依赖关系,然后再决定如何生成扁平的node_modules目录结构。npm必须为所有使用到的模块构建一个完整的依赖关系树,这是一个耗时的操作,是npm安装速度慢的一个很重要的原因。

由于我没有详细了解npm的变化,所以我想当然的以为每次运行npm install命令时,NPM都得从互联网上下载所有内容。

但是,我错了,npm是有本地缓存的,它保存了已经下载的每个版本的压缩包。本地缓存的内容可以通过npm cache ls命令进行查看。本地缓存的设计有助于减少安装时间。

总而言之,npm是一个成熟、稳定、并且有趣的包管理器。

Yarn
Yarn发布于2016年10月,并在Github上迅速拥有了2.4万个Star。而npm只有1.2万个Star。这个项目由一些高级开发人员维护,包括了Sebastian McKenzie(Babel.js)和Yehuda Katz(Ember.js、Rust、Bundler等)。

从我搜集到的情况来看,Yarn一开始的主要目标是解决上一节中描述的由于语义版本控制而导致的npm安装的不确定性问题。虽然可以使用npm shrinkwrap来实现可预测的依赖关系树,但它并不是默认选项,而是取决于所有的开发人员知道并且启用这个选项。

Yarn采取了不同的做法。每个yarn安装都会生成一个类似于npm-shrinkwrap.json的yarn.lock文件,而且它是默认创建的。除了常规信息之外,yarn.lock文件还包含要安装的内容的校验和,以确保使用的库的版本相同。

由于yarn是崭新的经过重新设计的npm客户端,它能让开发人员并行化处理所有必须的操作,并添加了一些其他改进,这使得运行速度得到了显著的提升,整个安装时间也变得更少。我估计,速度提升是yarn受欢迎的主要原因。

像npm一样,yarn使用本地缓存。与npm不同的是,yarn无需互联网连接就能安装本地缓存的依赖项,它提供了离线模式。这个功能在2012年的npm项目中就被提出来过,但一直没有实现。

yarn还提供了一些其他改进,例如,它允许合并项目中使用到的所有的包的许可证,这一点让人很高兴。

一个有趣的事情是,yarn文档的态度开始针对npm发生改变,因为yarn项目变得流行起来。

最开始的yarn公告是这么介绍yarn的安装的:

*最简单的入门方法是运行:
npm install -g yarn
yarn*
现在的yarn安装页面是这么说的:

注意:通常情况下不建议通过npm进行安装。npm安装是非确定性的,程序包没有签名,并且npm除了做了基本的SHA1哈希之外不执行任何完整性检查,这给安装系统程序带来了安全风险。

基于这些原因,强烈建议你通过最适合于你的操作系统的安装方法来安装yarn。

以这种速度发展下去的话,如果yarn要宣布他们自己的registry,让开发者慢慢淘汰npm的话,我们一点都不会感到惊讶。

看起来似乎要感谢yarn,npm终于意识到他们需要更加关注一些大家强烈要求的问题了。当我在审核我之前提到的强烈要求的“离线”功能时,我注意到这个需求正在被积极地修复之中。

pnpm
正如我所提到的,在pnpm的作者Zoltan Kochan发表了“为什么要用pnpm?”之后,我才知道pnpm。https://www.kochan.io/nodejs/why-should-we-use-pnpm.html

我不会介绍太多的细节(因为这篇文章已经发布很久了),但是你可以查看我的最初的帖子来寻找更多的内容,同时在Twitter上加入讨论。

但是

我想指出的是,pnpm运行起来非常的快,甚至超过了npm和yarn。

为什么这么快呢? 因为它采用了一种巧妙的方法,利用硬链接和符号链接来避免复制所有本地缓存源文件,这是yarn的最大的性能弱点之一。

使用链接并不容易,会带来一堆问题需要考虑。

正如Sebastian在Twitter上指出的那样,他最初是打算在yarn中使用符号链接的,但是由于其他一些原因放弃了它。

同时,正如在Github上拥有2000多个Star那样,pnpm能够为许多人所用。

此外,截至2017年3月,它继承了yarn的所有优点,包括离线模式和确定性安装。

<think>嗯,用户想了解npm、pnpmyarn之间的区别,特别是在功能、性能、缓存管理这些方面。我需要先回忆一下这三个工具的主要特点,然后对比它们的差异。 首先,npm是最早的包管理工具,作为Node.js的默认包管理器,用户基础大,生态支持好。但它在依赖管理上可能存在冗余,每个项目都会重复安装依赖,占用空间较大。性能方面,早期可能较慢,但后来有改进。缓存机制方面,npm有缓存,但可能不如其他工具高效。 然后是yarn,由Facebook等公司开发,主要是为了解决npm早期的一些问题,比如性能安全性。yarn引入了lock文件确保依赖一致性,支持并行安装,提高了速度。缓存方面,yarn的离线模式应该能有效利用缓存,减少网络请求。 pnpm比较新,最大的特点是使用内容寻址存储硬链接来共享依赖项。这样可以避免重复安装,节省磁盘空间,同时在多个项目中使用相同依赖时效率更高。缓存管理上,pnpm的缓存机制可能更高效,因为它直接链接到存储中的文件,而不需要解压。 接下来需要整理功能对比,比如依赖管理方式、lock文件的支持、工作区功能等。性能方面需要比较安装速度、磁盘空间使用。缓存管理部分要说明各自如何处理缓存,重用机制的区别。 还要注意用户提供的引用内容,比如引用1提到pnpm使用符号链接,缓存更快;引用2指出yarnpnpm支持并行安装,性能更好;引用3总结了三者的优缺点,比如pnpm的依赖共享稳定性问题。 用户可能需要知道如何根据项目需求选择工具,比如大型项目可能更适合pnpm节省空间,而稳定性成熟度可能让一些团队倾向npmyarn。此外,安全性方面yarnpnpm可能更好,特别是pnpm的严格结构避免非法访问。 需要确保回答结构清晰,分点对比,然后总结应用场景。最后生成相关问题,引导用户深入探讨,比如性能分析、优化方法、应用场景比较等。</think>### npm vs pnpm vs Yarn 对比分析 #### 1. **核心功能差异** - **npm**: - Node.js 默认包管理工具,生态最成熟,支持全局/局部安装。 - 早期依赖嵌套结构导致重复安装问题,现已改进为扁平化结构(但仍有潜在冲突)[^3]。 - 支持 `package-lock.json` 锁定依赖版本[^3]。 - **Yarn**: - 由 Facebook 等公司开发,核心目标是解决早期 npm 的性能安全问题。 - 引入 `yarn.lock` 文件确保依赖一致性,支持并行下载依赖提升速度[^2]。 - 提供 Workspaces(多包项目管理) Plug'n'Play(跳过 `node_modules` 直接解析依赖)。 - **pnpm**: - 采用**内容寻址存储****硬链接**技术,所有项目共享同一份依赖文件,节省磁盘空间[^1][^3]。 - 依赖树严格按层级结构存储,避免非法访问问题[^3]。 - 兼容 `package-lock.json` `yarn.lock`,迁移成本低。 --- #### 2. **性能对比** | 工具 | 安装速度 | 磁盘占用 | 网络优化 | |--------|-----------------|-------------|-------------------| | npm | 较慢(改进后中等) | 高(重复存储) | 依赖缓存需手动清理 | | Yarn | 快(并行下载) | 中等 | 离线模式完善 | | pnpm | 最快(硬链接复用)| 极低 | 缓存复用效率最高 | - **示例场景**: 若项目依赖 `lodash`,npm/Yarn 会在每个项目中单独存储,而 pnpm 只保存一份并通过硬链接共享。 --- #### 3. **缓存管理机制** - **npm/Yarn**: - 缓存依赖的压缩包(如 `.tar.gz`),安装时需解压到 `node_modules`[^3]。 - 清理命令:`npm cache clean --force` / `yarn cache clean`。 - **pnpm**: - 将依赖文件直接存储在全局目录(`~/.pnpm-store`),通过符号链接映射到项目。 - 无需解压,节省时间空间,清理命令:`pnpm store prune`。 --- #### 4. **安全性对比** - **npm**:历史漏洞较多(如依赖劫持),但近年来通过审计工具改进。 - **Yarn/pnpm**:默认校验依赖完整性,Yarn 的 Plug'n'Play 模式进一步减少攻击面。 --- #### 5. **适用场景总结** - **npm**:小型项目、Node.js 默认生态、对稳定性要求高。 - **Yarn**:大型单体应用、需 Workspaces 或严格依赖锁定的场景[^3]。 - **pnpm**:多项目协作、磁盘空间敏感、追求极速安装(如 Monorepo)[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值