跳到主要内容

谈谈包管理工具相关

npm和yarn都采用了铺平方案,有什么问题吗​

1、幽灵依赖问题

  • 幽灵依赖问题,造成了非法访问

  • 幽灵依赖 就是在依赖里没有声明,但在代码里却可以引入 【如果 A 依赖 B, B 依赖 C,那么 A 当中是可以直接使用 C 的】

    • 这种非法访问,是有隐患的,万一哪天别的包不依赖了这个包,你却引入了这个包,就会导致报错

2、一个包多版本问题

  • 依赖包多个版本的时候,只会提升一个,其余的版本也还是会复制很多次,导致浪费磁盘空间
    • 提升一个,就是说这个包会提升到顶层目录中,其余包的版本还是以嵌套的方式复制
  • 所以就有了pnpm,pnpm就解决了这个问题

pnpm在软链接和硬链接作用是什么?​

总结:

  • pnpm在 硬链接的作用可以在不同项目之间共享pnpm的store目录
  • pnpm在 软链接的作用 项目的node_modules这个文件夹中创建符号链接,包之间通过软链接的方式来相互引用依赖包,来复用相同版本的包依赖
    • 如果项目A依赖于项目B中的某个包,pnpm会创建一个软链接,将该包链接到项目A的node_modules中,而不是复制整个包。这可以节省磁盘空间

项目的所有的依赖都是从全局 store 硬链接到了 node_modules/.pnpm 下,然后之间通过软链接来相互依赖

硬链接:

.pnpm 中存放着所有的包。最终硬链接指向指向全局pnpm 仓库里的store目录下。

也就是说,我们所有的包,最终都以硬链接的形式,最终都在全局 pnpm/store 中,可以使得不同的项目从全局 store 寻找到同一个依赖,大大节省了磁盘空间。

  • 硬链接的作用可以在不同项目之间共享store文件

与软链接相比,硬链接的好处是它创建的链接可以被看作是源文件的副本,对应的文件节点数会增加,但它不会占用额外的磁盘空间,因为硬链接和源文件共享磁盘上的同一个数据块,只有在硬链接被删除时,才会释放对应的数据块

软链接:

pnpm 的软链接就是将 node_modules 里的文件软链接到对应的 .pnpm/[package_name]@version/node_modules/[package_name] 中。【pnpm软链接就是将node_mudules的文件软链接到对应的pnpm某个包的某个版本】

  • 软链接的设计保证不会出现幽灵依赖的问题
  • 通过软链接可以把 .pnpm的包软链接到当前项目 node_modules中,而不需要将包的源代码拷贝到当前项目,这种方式可以避免重复包拷贝和占用磁盘空间
    • 通过软链接来相互依赖
  • 软链接的作用是将一个包的源代码链接到多个项目中,避免在每个项目中都拷贝一份源代码

node_modules/.pnpm 可以理解为虚拟 store

npm2 是通过嵌套的方式管理 node_modules 的,会有同样的依赖复制多次的问题。

npm3+ 和 yarn 是通过铺平的扁平化的方式来管理 node_modules,解决了嵌套方式的部分问题,但是引入了幽灵依赖的问题,并且同名的包只会提升一个版本的,其余的版本依然会复制多次。

为什么会出现复制多次?

  • 多个包之间难免会有公共的依赖,这样嵌套的话,同样的依赖会复制很多次,会占据比较大的磁盘空间

pnpm 则是用了另一种方式,不再是复制了,而是都从全局 store 硬链接

到 node_modules/.pnpm,然后之间通过软链接来组织依赖关系。

pnpm是如何解决幽灵依赖问题​

  • pnpm采用了软链接的方式去引用依赖
  • pnpm通过软链接在项目的node_modules这个文件夹中创建符号链接,包之间通过软链接的方式来相互引用依赖包,从而解决这个幽灵依赖问题

pnpm为何速度快?​

  • 下载安装依赖的时候,pnpm会先检查全局的store目录,会从store目录硬链接到项目中,而不会重新安装依赖

  • 一个包的不同版本,pnpm 可以复用之前版本的代码。只会下载新版本的新文件,会复用之前版本的文件

pnpm 为何节省空间?​

  • 1、它解决了 npm/yarn 平铺 node_modules 带来的依赖项重复的问题 (doppelgangers)
  • 2、所有文件都保存在硬盘上的统一的位置。当安装软件包时, 其包含的所有文件都会硬链接自此位置,而不会占用 额外的硬盘空间。这让你可以在项目之间方便地共享相同版本的 依赖包。
  • 3、通过软链接可以把 .pnpm的包软链接到当前项目 node_modules中,而不需要在每个项目中复制依赖