Skip to content

pnpm的原理和用法

Posted on:February 19, 2023

先上图:

通过pnpm创建的项目目录结构

左图:通过npm(yarn) 安装的项目依赖的 node_moudles 文件结构(不仅包含项目本身的依赖,也包含各个 package 自身的依赖,即子依赖

右图:通过pnpm 安装的项目依赖 node_modules 的文件结构

可以明显看出,pnpm 的依赖更少(只有 package.json 中存在的 dependencies 和 devDependencies 才会被安装)

通过 npm2.x 安装依赖的缺点

通过npm创建的项目目录结构

  1. 包路径太长,在 Windows 系统下容易造成长路径问题
  2. 一个 package 会有多个副本存在,造成多余的依赖,导致不必要的磁盘占用 (上图中的 foo 引用 bar,如果这时存在另一个文件 aaa 也引用了 bar package,那么这个 aaa 下的 node_modules 也会存在一个 bar package)

通过 npm3.x / yarn 安装依赖的问题

npm3.x 通过拉平(flattered)依赖关系解决了npm@2.x依赖多个副本的问题,node_modules 文件结构如下:

node_modules

但依然存在以下问题:

  1. 包可以互相访问(因为 node_modules 结构被拉平了,包与包之间在同一层级结构下,那么一个 package 可以访问任何一个 package,即使这个包并没有引用另一个包),可能会造成安全问题(幽灵依赖
  2. 因为这个 flat 算法的复杂度高,所以安装速度很慢
  3. 有一些包不得不在 node_modules 文件夹下,如果强行 flat,可能会有引用问题
  4. 不同包会依赖同一个包的不同版本,flat 后可能会报错

yarn 的处理基本和npm@3.x一致

pnpm 如何解决 npm 的问题

pnpm 会在磁盘上新建一个中心化的pnpm store来保存所有的依赖, 后面在项目中再次使用都会直接使用  hardlink(硬链接),将项目中的包 link 到 store,从而大大节省磁盘空间。

pnpm  首先将依赖安装到全局  store,然后通过  symbolic link  和  hard link  来组织目录结构,将全局的依赖链接到项目中,将项目的直接依赖链接到  node_modules  的顶层,所有的依赖则平铺于  node_modules/.pnpm  目录下,实现了所有项目的依赖共享  store  的全局依赖,解决了幽灵依赖和 NPM 分身的问题。(如果项目引用了某个依赖的子依赖,pnpm 会报错,必须要在项目 package.json 里引入该 sub dependence,即用了 pnpm 能保证代码引入的包必须出现在 package.json 文件里