pnpm 先进的包管理工具


theme: smartblue

pnpm 是什么

速度快、节省磁盘空间的软件包管理器

pnpm 的优点

  1. 速度快 pnpm 是同类工具速度的将近 2 倍
  2. 高效 node_modules 中的所有文件均克隆或硬链接自单一存储位置
  3. 支持workspace pnpm 内置了对单个源码仓库中包含多个软件包的支持
  4. 安全 pnpm 创建的 node_modules 默认并非扁平结构,因此代码无法对任意软件包进行访问
    下面是pnpm 和其他包管理工具的对比图

6ae193c1cef154e45716ca62d9b91e3.png
我们可以看到pnpm是遥遥领先

其他包管理工具的问题

目前大部分用得包管理工具有 npm yarn 在使用过程中难免会遇到一些问题,安装速度慢,存在幽灵依赖等问题。那么我们接下来看看npm 和 yarn 的问题

npm

npm v2

在早期npm管理包的模式非常简单。它会去读取每个模块的依赖,然后下载相应版本的依赖去当前目录下的node_modules. 如果当前模块还存在其他依赖,接着会继续下载相应的依赖到该模块的node_modules.一直会递归下去,直至不存在任何依赖。最终会生成一个庞大的树结构。
这么会存在什么问题呢?

  1. 模块依赖太深。某个模块出问题,很难去定位
  2. 在windows下。路径长度会有限制
  3. 会下载多个重复模块,导致大量资源浪费
  4. 下载速度过慢,开发效率低下
    在这个时候 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的流程

49a6b72e21fc232579fec9aa3cc4fdf.png

那这种模式就真的完美无瑕了吗? 其实他并没有解决V3中的重复依赖以及幽灵依赖的问题问题

yarn

yarn 是一个由Facebook、Google、Exponent和Tilde构建的新的JavaScript包管理器,是在npm v3的时候推出的。主要是为了解决历史上npm的不足之处(依赖不确定以及下载速度慢)
yarn主要有一下特点

  1. 确定性 通过yarn.lock文件,确定node_modules的依赖问题(npm v5 也实现了同样的功能)
  2. 扁平化安装 将不同版本的依赖包 按照一定的策略,归结为单个版本 以避免创建多个版本造成工程的冗余(npm v5实现了相似功能)
  3. 安装速度更快: 并行安装,能够更好的利用网络资源,引入了一种安装失败的重试机制
  4. 采用缓存机制 (npm v5实现了相似功能)
  5. workspace(npm V7 实现了相似的功能)

pnmp怎么解决这种问题

通过了解npm 和 yarn 我们知道,其实他们还是会存在一定的问题,还是会存在重复的依赖问题,并且扁平化之后会带来一些新的问题,某个包在项目中不是依赖,但是项目中还是可以去引用。这会带来一些安全性的问题。那么要想知道pnpm是怎么解决这个问题的。我们必须要了解一下软连接和硬链接

Inode

在我们平时工作中,都会有一些文件 或者资料,那么我们计算机是怎么去存取这些文件的呢?
在linux系统里。这些文件资料会分为两个部分。 一部分是我们真实的文件数据,一部分是是存储文件的元数据。 比如文件的创建者。文件的权限。文件的创建时间。等等。那么我们把存储这些文件的信息的区域称之为Inode. 对于每一个Inode都有一个编号,用于我们操作系统去识别Inode。在操作系统底层,它并不会去在意文件名,而是通过Inode去识别文件。当我们打开文件的时候。操作系统其实主要做了三部工作

  1. 通过文件名去寻找Inode
  2. 通过Inode编号去获取Inode信息
  3. 通过Inode信息找到文件信息的磁盘区域

软链接(Symbolic links)

符号连接(Symbolic Link),也叫软连接。
软链接文件有类似于Windows的快捷方式。
它实际上是一个特殊的文件。在符号连接中,文件实际上是一个文本文件,其中包含的有另一文件的位置信息。
可以通过 ln -s 原始文件 链接文件创建
7086b97511afeebc0827b5cdf084ecb.png

硬链接(Hard links)

硬连接指通过索引节点来进行连接。
在Linux的文件系统中,保存在磁盘分区中的文件不管是什么类型
都给它分配一个编号,称为索引节点号(Inode Index)。
在Linux中,多个文件名指向同一索引节点是存在的。一般这种连接就是硬连接。
可以通过 ln 原始文件 链接文件创建
e95052c13cb791c9d60299360661c5e.png

软链接和硬链接的区别

软链接

  1. 类似于windows的快捷方式
  2. 支持跨文件系统或者目录
  3. inode 是不同的
  4. 创建和删除软链接是不会增加链接数
  5. 链接中任何一个文件发生改变,都会同步到其他文件
  6. 链接文件中只记录原始文件的路径,不记录原始文件的内容
  7. 如果源文件删除。软链接将不能访问文件
  8. 会占用一定的磁盘空间

硬链接

  1. 硬链接是原始文件的一个镜像副本
  2. 不可以跨文件系统创建
  3. 硬链接只能指向文件
  4. inode是相同的
  5. 链接文件记录了原始文件的内容
  6. 原始文件被移除了。链接文件不会受到影响
  7. 几乎不占用磁盘空间

了解了软硬连接之后,我们就可以更快的知道pnpm的实现方式。如官方的图

ccf85078579246130c8323e34a70ad1.png
通过上面的图可以得知pnpm 的一个包全局只会保存一份,其他的都是通过软硬连接。那么这样我们的下载速度也会变快。 同时也可以解决我们的幽灵依赖问题。

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容