pnpm、Yarn 和 npm 都是 JavaScript 生态系统中流行的包管理工具,但它们在设计理念、性能特点和功能上存在一些差异。以下是这三种工具的主要区别:
1. 安装机制
-
npm:
- 使用扁平化的
node_modules
结构(从版本 3 开始),即所有依赖尽可能地安装在顶层。 - 每次安装时都会复制文件到
node_modules
文件夹中。
- 使用扁平化的
-
Yarn:
- 同样使用扁平化的
node_modules
结构。 - 引入了全局缓存来避免重复下载相同的包,并通过硬链接将缓存中的包链接到项目中。
- 使用锁定文件 (
yarn.lock
) 来确保跨环境的一致性。
- 同样使用扁平化的
-
pnpm:
- 使用非扁平的
node_modules
结构,保持依赖树的层次结构。 - 采用内容可寻址存储(CAS)来存储所有已下载的包,通过符号链接或硬链接将这些包引入项目的
node_modules
中。 - 这种方式显著减少了磁盘空间占用并提高了安装速度。
- 使用非扁平的
2. 性能
- npm:随着版本迭代,npm 的性能有了很大提升,但在处理大型项目时仍可能较慢。
- Yarn:比早期版本的 npm 更快,特别是在网络请求方面进行了优化,减少了冗余下载。
- pnpm:通常被认为是最快的包管理器之一,因为它避免了不必要的文件复制,利用了更高效的依赖解析和安装方法。
3. 依赖解析规则
- npm:默认情况下允许幽灵依赖的存在,即项目可以访问未显式声明的依赖。
- Yarn:提供了较为严格的依赖解析规则,但仍可能存在某些情况下幽灵依赖的问题。
- pnpm:采用了最严格的依赖解析规则,确保每个包只能访问自己声明的直接依赖及其子依赖,从而彻底消除了幽灵依赖的可能性。
4. 工作区支持
- npm:从 v7 开始正式支持工作区(workspaces),允许多个包共享一个根
package.json
文件。 - Yarn:很早就支持了工作区,并且有丰富的配置选项。
- pnpm:也支持工作区,并且由于其高效的依赖管理和安装机制,在多包仓库(monorepos)中表现尤为出色。
5. 锁文件
- npm:使用
package-lock.json
文件。 - Yarn:使用
yarn.lock
文件。 - pnpm:使用
pnpm-lock.yaml
文件,提供与 Yarn 类似的锁定机制以保证依赖版本的一致性。
6. 社区和支持
- npm:作为官方 Node.js 包管理器,拥有最大的市场份额和最强的社区支持,如果你重视兼容性和社区资源,npm 可能是一个不错的选择。
- Yarn:由 Facebook 发起,得到了广泛采用,尤其在 React 社区中非常流行。如果你希望更快的安装速度和更好的安全性,那么 pnpm 或 Yarn 都比价适合你。
- pnpm:虽然相对较新,但因其独特的优势迅速获得了开发者的好评,尤其是在对性能敏感的应用场景中。对于大型项目或者 monorepo 管理,pnpm 凭借其独特的依赖管理和出色的性能表现尤为突出。
产生幽灵依赖的原因?
在项目中,它的 node_modules 里有依赖 A,A 又依赖了 B,而现有 npm 的依赖存储方式是将所有依赖都铺平了放在 node_modules 下(就是无论层级关系事什么都铺平放)。这个时候我们可以在项目中直接引用 B。
产生幽灵依赖的场景 1:
在项目中,它的 node_modules 里有依赖 A,A 又依赖了 B,而你的项目中引入了依赖 B,这个时候将依赖 A 删除,依赖 B 也会跟着删除。再去访问 B 里面的方法就会报错。