1. 介绍及发展历史
以下是npm
、yarn
和pnpm
包管理工具的介绍:
npm
:npm
是最早的Node.js包管理工具,由Isaac Z. Schlueter于2010年创建。它是Node.js社区默认的包管理工具,也是最流行的工具之一。它具有简单易用、灵活、生态系统完备等优点,在社区得到了广泛认可和使用。yarn
:yarn
是由Facebook于2016年发布的另一款Node.js包管理工具,旨在提高npm
的安装速度和可靠性。yarn
具有离线安装、并行下载、版本锁定、优先使用本地缓存等特性,已成为许多开发者的选择。pnpm
:pnpm
是最近的Node.js包管理工具之一,它在2016年由Zoltán Kochan开发。pnpm
的设计思想是使用符号链接和递归锁定来优化依赖项管理,从而提高安装速度和减少磁盘空间占用。近年来,pnpm
在开源社区中逐渐得到认可,并且已经被许多公司和组织所使用。
总之,随着Node.js生态系统的不断壮大,像npm
、yarn
和pnpm
这样的包管理工具的出现,使得Node.js开发者可以更有效地管理和分享代码库,提高项目的开发效率。
2. 更新历史
2.1 npm
的一些重要更新历史和变化:
npm
1.0.0: 该版本是npm
的第一个稳定版本,标志着npm
从Node.js
独立出来,成为了一个独立的包管理器。该版本引入了npm shrinkwrap
命令,用于创建和维护项目的依赖关系树。npm
2.0.0: 该版本引入了scoped packages
,允许使用者将包命名为@namespace/package-name
的形式,以避免包名称冲突。该版本还引入了自动压缩,使安装包时的下载和解压时间减少。npm
3.0.0: 该版本引入了扁平化依赖关系树,使依赖项更容易管理和理解。此版本也使npm
与yarn
等新的竞争对手相比,更好地解决了依赖项的解析问题。npm
5.0.0: 该版本引入了npm ci
命令,可以用于快速、干净、准确地安装项目的依赖关系。此版本还引入了本地缓存,以避免在网络上下载相同的依赖项。npm
7.0.0: 该版本引入了与Node.js 15
捆绑在一起,引入了许多新特性,包括Workspaces
、自动垃圾回收、改进的CLI和搭配安装。Workspaces
是一个大型项目管理工具,可以同时管理多个包并在它们之间共享依赖项。
node对于npm的版本
除了这些重要的版本历史和变化之外,npm
还对性能、安全、易用性和用户体验等方面进行了许多改进
2.2 Yarn 的一些重要更新历史:
- Yarn 0.16.0: 这是 Yarn 的第一个公共版本,发布于 2016 年。它引入了 Yarn 的锁定文件机制,以解决因不同依赖版本之间的冲突而导致的一些问题。此外,它还提供了各种命令来管理依赖项,比如 yarn add、yarn remove 和 yarn upgrade 。
- Yarn 1.0.0: Yarn 1.0.0 发布于 2017 年,其中包含了一些新特性和改进,如安装顺序的优化、自适应网络速度的下载速度控制和完全离线的安装等。
- Yarn 2.0.0: Yarn 2.0.0 发布于 2020 年,其中最大的变化是默认使用 PnP (plug-n-play) 解决方案,这是一种新的依赖项解决方案,将依赖项放在项目的虚拟文件系统中,以提高速度和可靠性。此外,它还包括其他一些新功能,例如交互式提示符和基于 node-modules 的缓存目录结构。
- Yarn 3.0.0: Yarn 3.0.0 pre-release 发布于 2021 年,它引入了一些重要的变化。最重要的是它摆脱了之前几个版本中使用的 PnP 方案,改为使用 Zero-Installs 方案,以进一步优化依赖项安装和管理。此外,它还提供了单独运行 Yarn 命令的能力并增强了缓存管理。
除了这些版本之外,Yarn 还对其用户界面和其他属性进行了很多改进,以便更好地管理现代化的 JavaScript 项目依赖性。
2.3 pnpm 的一些重要更新历史:
- pnpm 1.0.0: 这是 pnpm 的第一个正式版本,发布于 2016 年。它引入了 pnpm 的唯一依赖解决方案,该方案能够解决依赖项大小的问题,以及使用硬链接和符号链接来节省空间。
- pnpm 2.0.0: pnpm 2.0.0 发布于 2017 年,其中包含了一些新特性和改进,如安装顺序优化和改进的缓存机制等。
- pnpm 3.0.0: pnpm 3.0.0 发布于 2018 年,其中最大的变化是引入了工作区安装 (workspaces),允许您在一个代码库中管理多个相关项目的依赖关系。此外,它还包括其他一些新功能,例如可选的锁版本选项和增强的缓存机制。
- pnpm 4.0.0: pnpm 4.0.0 发布于 2019 年,引入了一些新特性和改进,例如并行安装和增强的配置选项。
- pnpm 5.0.0: pnpm 5.0.0 发布于 2020 年,其中最大的变化是切换到了 ES Modules,并且采用了全新的 pnpm 子命令系统来提高性能和用户体验。此外,它还包括其他一些新功能,例如增强的依赖分析和工作区安装的功能增强。
- pnpm 6.0.0: pnpm 6.0.0 发布于 2021 年,引入了一些新特性,包括并发下载、改进的锁版本算法、对 Windows 文件系统的改进支持等。
上述更新只是 pnpm 的一部分,它们展示了 pnpm 不断演进和创新的过程,力求提供更好的体验和效果。
3. 具体使用情况
3.1 npm2使用
为了了解npm之前安装依赖的情况,先使用n进行切换版本,node版本切换后npm版本会随之变化,先使用npm2版本进行尝试.
用 node 版本管理工具把 node 版本降到 4 使用n 4
,那 npm 版本就是 2.x 了。
- 初始化项目npm init -y
- 安装npm i koa -S
- 查看包安装情况
同一个依赖depd重复安装
嵌套层级过深,每个依赖都有自己的 node_modules
大小
上面会产生几个问题:
- 公共的依赖不能复用
- windows 的文件路径最长是 260 多个字符,这样嵌套是会超过 windows 路径的长度限制的
- 同样的依赖会复制很多次,会占据比较大的磁盘空间
为了解决上述问题,出来新的解决方案了,就是 yarn
3.2 yarn、npm8 使用
- 将版本提升否则yarn初始化失败
- 初始化项目yarn init -y
- 安装依赖 yarn add koa
yarn 是怎么解决依赖重复很多次,嵌套路径过长的问题的呢?
铺平。所有的依赖不再一层层嵌套了,而是全部在同一层,这样也就没有依赖重复多次的问题了,也就没有路径过长的问题了。
为什么还有嵌套呢?
因为一个包是可能有多个版本的,提升只能提升一个,所以后面再遇到相同包的不同版本,依然还是用嵌套的方式。
大小:
npm8
npm 后来升级到 3 之后,也是采用这种铺平的方案了,和 yarn 很类似:
上述方式没有缺陷吗?
- 幽灵依赖
最主要的一个问题是幽灵依赖,也就是你明明没有声明在 dependencies 里的依赖,但在代码里却可以 require 进来。
这个也很容易理解,因为都铺平了嘛,那依赖的依赖也是可以找到的。
但是这样是有隐患的,因为没有显式依赖,万一有一天别的包不依赖这个包了,那你的代码也就不能跑了,因为你依赖这个包,但是现在不会被安装了。
这就是幽灵依赖的问题。
- 磁盘空间浪费
就是上面提到的依赖包有多个版本的时候,只会提升一个,那其余版本的包不还是复制了很多次么,依然有浪费磁盘空间的问题。
那社区有没有解决这俩问题的思路呢?
pnpm 就出来了
3.3 pnpm使用
npm3 和 yarn 为什么要做 node_modules 扁平化?不就是因为同样的依赖会复制多次,并且路径过长在 windows 下有问题?
那如果不复制,比如通过link的方式解决磁盘空间问题。
前置知识:
软硬链接:
软链接(软连接):是一个指向另一个文件的路径的特殊文件。软链接是对实际文件的引用,它不包含实际内容,而是只包含指向实际文件的地址。当目标文件被删除后,软链接将不再有效。可以创建不同文件系统之间的软链接,实现跨文件系统的链接。
硬链接(硬连接):是指与一个文件关联的两个或多个目录条目。硬链接只有在与原始文件在同一个文件系统上时才有效。硬链接的创建方式是复制索引节点,因此,硬链接与原始文件有相同的属性。硬链接本身不包含源文件的路径,只有对应的索引节点信息。删除源文件不影响硬链接,因为硬链接不依赖于源文件的路径。硬链接实际上允许一个文件在不同目录中具有不同的文件名。
在 pnpm 中,软链接和硬链接的使用取决于包管理策略。通常情况下,pnpm 通过软链接的方式将依赖关系连接到项目。
mac中创建软硬链接:
在 macOS 系统中,可以通过命令行使用 ln
命令来创建软链接和硬链接。
创建软链接(符号链接):
ln -s <源文件或目录> <链接文件或目录>
例如,创建一个名为 prettier-ln
的软链接,指向名为 prettier
的源文件,命令如下:
ln -s sourceCode/prettier prettier-ln // 目录
ln -s sourceCode/prettier/package.json pkg-ln.json // 文件
创建软链接解决重复安装依赖磁盘空间问题
创建硬链接:
ln <源文件> <链接文件>
例如,创建一个名为 prettier-hard
的硬链接,指向名为 prettier
的源文件,命令如下:
ln -s sourceCode/prettier prettier-hard // 目录
ln -s sourceCode/prettier/package.json pkg-hard.json // 文件
修改硬链接的内容,会影响原文件,删除也不会影响原文件。
请注意,硬链接不能用于目录,也不能跨越不同的文件系统。在这些情况下,请使用软链接。
- 初始化项目 pnpm init
- 安装依赖pnpm add koa
包是从全局 store 硬连接到虚拟 store 的,这里的虚拟 store 就是 node_modules/.pnpm。
只在全局仓库保存一份 npm 包的内容,其余的地方都 link 过去,.npm
使用硬链接这样不会有复制多次的磁盘空间浪费,而且也不会有路径过长的问题。因为路径过长的限制本质上是不能有太深的目录层级,现在都是各个位置的目录的 link,并不是同一个目录,所以也不会有长度限制。
大小:
结合图理解
解决了npm、yarn的问题