pnpm作为目前比较流行的包管理器之一,主要特点是速度快,节省磁盘空间。本文将介绍pnpm的底层实现,帮助大家理解pnpm的原理。pnpm简介pnpm的意思是performantnpm,意思是高性能的npm,从官网提供的benchmarks也可以看出npm、yarn、yarn_pnp在intall、update等场景下都有很好的性能优势:node_modules的嵌套目录结构在npm@2早期版本,对应Node.js4.x及之前的版本,node_modules是安装时嵌套结构的简单示例。demo-foo和demo-baz都依赖于example-bar。当同时安装demo-foo和demo-baz时,会生成如下node_modules结构:node_modules└─demo-foo├─index.js├─package.json└─node_modules└─demo-bar├─index.js└─package.json└─demo-baz├─index.js├─package.json└─node_modules└─demo-bar├─index.js└─package.json虽然此时的目录结构比较清晰,每个依赖包都会有自己的node_modules,相同的依赖不会被复用,比如上面的同一个依赖demo-bar安装了两次。另一个问题是windows的最长路径限制。在复杂的项目场景中,当依赖层次很深时,依赖路径往往会超过长度限制。扁平化结构为了解决以上问题,yarn提出了扁平化结构设计,将所有的依赖扁平化在node_modules中,后面npmv3版本的实现也类似,所以使用yarn或者npm@3+来安装上面的例子,你将得到以下平面目录结构:node_modules└─demo-bar├─index.js└─package.json└─demo-baz├─index.js└─package.json└─demo-foo├─index.js└─package.json另外,对于同一个依赖的不同版本,只会升级其中一个,其余版本仍会嵌套在对应的包中,比如上面demo-foo中对demo-bar的依赖升级到v1.0.1版本,会得到如下结构,具体提升到哪个版本取决于安装顺序(例子):node_modules└─demo-bar├─index.js└─package.json└─demo-baz├─index.js├─package.json└─node_modules└─demo-bar├─index.js└─package.json└─demo-foo├─index.js├─package.json└─node_modules└─demo-bar├─index.js└─package.json扁平化结构的问题扁平化解决方案并不完美,但引入了一些新问题:Phantomdependencies幻影依赖(Phantomdependencies)是指没有在package.json中显式声明,但可以直接引用对应包的依赖。这个问题是flat结构导致的,dependencies的依赖也会包含在项目中的最顶层node_modules也可以直接引用。当有一天这个子依赖不再是引用包的依赖时,项目中的引用就会出现问题。NPMdoppelgangers指的是同一依赖项的不同版本。由于提升机制,只会提升一个,其他版本可能会重复安装,还是上面的例子,当依赖的demo-bar的依赖升级到v1.0.1时,v1.0.0版本就是依赖的demo-foo和demo-baz会嵌套形式重复安装:node_modules└─demo-bar//v1.0.1├─index.js└─package.json└─demo-baz├─index.js├─package.json└─node_modules└─demo-bar//v1.0.0├─index.js└─package.json└─demo-foo├─index.js├─package.json└─node_modules└─demo-bar//v1.0.0├─index.js└─package.jsonpnpm解题思路pnpm首先将依赖安装到全局store,然后通过符号链接和硬链接组织目录结构,将全局依赖链接到项目中,将项目的直接依赖链接起来项目到node_modules顶层,所有依赖都布局在node_modules/.pnpm目录下,实现了所有项目依赖的全局依赖和共享存储,解决了幽灵依赖和npm克隆问题。符号链接和硬链接链接是操作系统中的文件共享方式,符号链接是符号链接,也称为软链接,硬链接是硬链接。从使用的角度来看,两者没有区别,都支持读写。如果是可执行文件,也可以直接执行。主要区别在于底层原理不同:硬链接不创建新的inode(索引节点),源文件和硬链接指向同一个索引节点。硬链接不支持目录,只支持文件级别,不支持跨分区删除源文件。所有硬链接后,文件实际上被删除了。源文件的路径存放在符号链接symboliclink中,指向源文件。类似于Windows快捷方式符号链接支持目录和文件,区别于源文件。inode值不同,文件类型也不同,所以可以跨分区访问符号链接。删除源文件后,符号链接仍然存在,但无法通过它访问源文件。如何创建链接#symbolicinkln-smyfilemysymlink#hardlinklnmyfilemysymlinkpnpm在pnpm中,会把依赖安装到当前分区的
