# Pnpm

# 原理

# 1. 硬链接和符号链接机制

  • 全局存储

pnpm会将所有项目的依赖包下载到全局的仓库,通常是在用户的主目录下面(pnpm store path)。

  • 硬链接

每个文件都是一个指针,指向具体的文件数据,所以不会产生额外的磁盘占用,可以重复创建各种硬链接,文件夹不能创建硬连接。

硬链接

pnpm会在项目的node_modules中创建指向全局存储中相应的包的链接,只会占用一次空间,每个项目都可以访问到自己项目的依赖包副本。

  • 符号链接

符号链接指向的是创建出来的文件,一旦一个删除,另一个也会无效,文件和文件夹都可以创建。

符号链接

  • node 处理

硬链接: node 无法区别对待,当作一个普通文件。 符号链接: 符号链接指向的是另一个文件/文件夹,当 node 执行文件的时候,使用的是原始路径。

# 2. 严格的依赖隔离

pnpm每个包只能访问自身声明的依赖,杜绝幽灵依赖,与传统npm不同。

# 具体目录结构

pnpmnode_modules布局使用符号链接来创建依赖关系的嵌套结构。

比如项目依赖foo@1.0.0这个包,而foo@1.0.0依赖bar@1.0.0

  1. 首先会创建所有依赖到.pnpm中,这些自身都属于硬连接,是真实存在的。
node_modules
└── .pnpm
    ├── bar@1.0.0
    │   └── node_modules
    │       └── bar -> <store>/bar
    │           ├── index.js
    │           └── package.json
    └── foo@1.0.0
        └── node_modules
            └── foo -> <store>/foo
                ├── index.js
                └── package.json


  1. 符号链接依赖项

根据依赖关系,创建符号链接。

node_modules
└── .pnpm
    ├── bar@1.0.0
    │   └── node_modules
    │       └── bar -> <store>/bar
    └── foo@1.0.0
        └── node_modules
            ├── foo -> <store>/foo
            └── bar -> ../../bar@1.0.0/node_modules/bar
  1. 处理直接依赖关系。

最终只有foo作为项目的依赖。

node_modules
├── foo -> ./.pnpm/foo@1.0.0/node_modules/foo
└── .pnpm
    ├── bar@1.0.0
    │   └── node_modules
    │       └── bar -> <store>/bar
    └── foo@1.0.0
        └── node_modules
            ├── foo -> <store>/foo
            └── bar -> ../../bar@1.0.0/node_modules/bar