theme: smartblue
pnpm 是什么
速度快、节省磁盘空间的软件包管理器
pnpm 的优点
- 速度快 pnpm 是同类工具速度的将近 2 倍
- 高效 node_modules 中的所有文件均克隆或硬链接自单一存储位置
- 支持workspace pnpm 内置了对单个源码仓库中包含多个软件包的支持
- 安全 pnpm 创建的 node_modules 默认并非扁平结构,因此代码无法对任意软件包进行访问
下面是pnpm 和其他包管理工具的对比图
我们可以看到pnpm是遥遥领先
其他包管理工具的问题
目前大部分用得包管理工具有 npm yarn 在使用过程中难免会遇到一些问题,安装速度慢,存在幽灵依赖等问题。那么我们接下来看看npm 和 yarn 的问题
npm
npm v2
在早期npm管理包的模式非常简单。它会去读取每个模块的依赖,然后下载相应版本的依赖去当前目录下的node_modules. 如果当前模块还存在其他依赖,接着会继续下载相应的依赖到该模块的node_modules.一直会递归下去,直至不存在任何依赖。最终会生成一个庞大的树结构。
这么会存在什么问题呢?
- 模块依赖太深。某个模块出问题,很难去定位
- 在windows下。路径长度会有限制
- 会下载多个重复模块,导致大量资源浪费
- 下载速度过慢,开发效率低下
在这个时候 node_modules被称为依赖地狱
目录结构如下
├── node_modules
│ ├── A@1.0.0
│ │ └── node_modules
│ │ │ | └── D@1.0.0
│ │ │ | └── node_modules
│ │ │ | | └── F@1.0.0
│ ├── B@1.0.0
│ │ └── node_modules
│ │ │ └── D@2.0.0
│ └── C@1.0.0
│ │ └── node_modules
│ │ │ └── D@2.0.0
npm v3
为了解决npm v2 这种依赖地狱的问题。npm v3 尝试把依赖以及依赖的依赖都尽量的平铺在项目根目录下的node_modules文件夹下以共享使用;如果遇到因为需要的版本要求不一致导致冲突,没办法放在平铺目录下,回退到npm v2的处理方式,在该模块下的node_modules里存放冲突的模块。
npm怎么做到扁平化的呢?
先遍历所有的项目依赖关系,然后再决定如何生成扁平的node_modules目录结构。npm必须为所有使用到的模块构建一个完整的依赖关系树,这是一个耗时的操作,是npm安装速度慢的一个很重要的原因。
npm v3就是完美解决方案吗?
npm v3是否是完美解决方案呢? 其实不是,这种还是会存在一定的问题. 主要是依赖结构不确定性。并且存在幽灵依赖,可能会出现下面两种结果
├── node_modules
│ ├── D@1.0.0
│ ├── F@1.0.0
│ ├── A@1.0.0
│ │ └── node_modules
│ ├── B@1.0.0
│ │ └── node_modules
│ │ │ └── D@2.0.0
│ └── C@1.0.0
│ │ └── node_modules
│ │ │ └── D@2.0.0
├── node_modules
│ ├── D@2.0.0
│ ├── F@1.0.0
│ ├── A@1.0.0
│ │ └── node_modules
│ │ │ | └── D@1.0.0
│ ├── B@1.0.0
│ └── C@1.0.0
可以看到node_modules中D模块可能是1.0.0 或者2.0.0。这主要看npm解析模块依赖的时候。 这就要取决于A B C 三个模块在package.json文件的位置。当A在前面,那么D@1.0.0就在最顶层。反之D@2.0.0就在最顶层。当然npm v3就可以解决之前的依赖地狱的问题。但是还是会有一定的重复依赖
npm V5
npm V5主要解决v3存在模块依赖不确定性的问题。主要通过package-lock.json文件。
npm的流程
那这种模式就真的完美无瑕了吗? 其实他并没有解决V3中的重复依赖以及幽灵依赖的问题问题
yarn
yarn 是一个由Facebook、Google、Exponent和Tilde构建的新的JavaScript包管理器,是在npm v3的时候推出的。主要是为了解决历史上npm的不足之处(依赖不确定以及下载速度慢)
yarn主要有一下特点
- 确定性 通过yarn.lock文件,确定node_modules的依赖问题(npm v5 也实现了同样的功能)
- 扁平化安装 将不同版本的依赖包 按照一定的策略,归结为单个版本 以避免创建多个版本造成工程的冗余(npm v5实现了相似功能)
- 安装速度更快: 并行安装,能够更好的利用网络资源,引入了一种安装失败的重试机制
- 采用缓存机制 (npm v5实现了相似功能)
- workspace(npm V7 实现了相似的功能)
pnmp怎么解决这种问题
通过了解npm 和 yarn 我们知道,其实他们还是会存在一定的问题,还是会存在重复的依赖问题,并且扁平化之后会带来一些新的问题,某个包在项目中不是依赖,但是项目中还是可以去引用。这会带来一些安全性的问题。那么要想知道pnpm是怎么解决这个问题的。我们必须要了解一下软连接和硬链接
Inode
在我们平时工作中,都会有一些文件 或者资料,那么我们计算机是怎么去存取这些文件的呢?
在linux系统里。这些文件资料会分为两个部分。 一部分是我们真实的文件数据,一部分是是存储文件的元数据。 比如文件的创建者。文件的权限。文件的创建时间。等等。那么我们把存储这些文件的信息的区域称之为Inode. 对于每一个Inode都有一个编号,用于我们操作系统去识别Inode。在操作系统底层,它并不会去在意文件名,而是通过Inode去识别文件。当我们打开文件的时候。操作系统其实主要做了三部工作
- 通过文件名去寻找Inode
- 通过Inode编号去获取Inode信息
- 通过Inode信息找到文件信息的磁盘区域
软链接(Symbolic links)
符号连接(Symbolic Link),也叫软连接。
软链接文件有类似于Windows的快捷方式。
它实际上是一个特殊的文件。在符号连接中,文件实际上是一个文本文件,其中包含的有另一文件的位置信息。
可以通过 ln -s 原始文件 链接文件创建
硬链接(Hard links)
硬连接指通过索引节点来进行连接。
在Linux的文件系统中,保存在磁盘分区中的文件不管是什么类型
都给它分配一个编号,称为索引节点号(Inode Index)。
在Linux中,多个文件名指向同一索引节点是存在的。一般这种连接就是硬连接。
可以通过 ln 原始文件 链接文件创建
软链接和硬链接的区别
软链接
- 类似于windows的快捷方式
- 支持跨文件系统或者目录
- inode 是不同的
- 创建和删除软链接是不会增加链接数
- 链接中任何一个文件发生改变,都会同步到其他文件
- 链接文件中只记录原始文件的路径,不记录原始文件的内容
- 如果源文件删除。软链接将不能访问文件
- 会占用一定的磁盘空间
硬链接
- 硬链接是原始文件的一个镜像副本
- 不可以跨文件系统创建
- 硬链接只能指向文件
- inode是相同的
- 链接文件记录了原始文件的内容
- 原始文件被移除了。链接文件不会受到影响
- 几乎不占用磁盘空间
了解了软硬连接之后,我们就可以更快的知道pnpm的实现方式。如官方的图
通过上面的图可以得知pnpm 的一个包全局只会保存一份,其他的都是通过软硬连接。那么这样我们的下载速度也会变快。 同时也可以解决我们的幽灵依赖问题。
暂无评论内容