npm 作为最广泛使用的包管理工具之一,虽然功能强大,但在实际使用中,开发者可能会遇到一种令人头疼的问题——幻影依赖。
npm幻影依赖
在项目中安装了库A,但是库A又依赖库B,所以你的项目中其实可以直接使用库B,即使你并没有直接安装库B,这就是幻影依赖,也叫幽灵依赖。最常见的场景就是:你的项目自己开发的很好,别人一拉代码,安装依赖运行不起来...
造成的问题:
- 版本问题
- 依赖丢失问题
如果A是开发环境依赖,那么生产环境是不会打包的(A和B),开发时我们使用了B,但是生产环境没有,导致依赖丢失
依赖图
早期的npm文件树:库A和库B都依赖库D,那就在A和库B的文件夹下都存放库D,这种放方式导致依赖体积庞大
npm的处理方式
将所有的包打平(flat,扁平结构),全部作为同一级存放在node_modules下(借鉴yarn),看看pnpm的解决方式
pnpm软链接
软链接是一个特殊类型的文件,它包含了另一个文件的路径。
pnpm是创建一个仓库,将直接依赖和间接依赖全部放进去,当我们使用时不会直接在这里寻找
pnpm在建立node_modules文件树时,会采用npm最早的那种做法(下图左)
巧妙的是:这里的树里面的文件夹都不占用磁盘空间,通过软链接的方式找到仓库里面的依赖包来使用
- node_modules文件夹下只有我们手动安装的依赖,
.pnpm下保存了手动安装的依赖和所有的幻影依赖,以平铺的形式存放。
对于那些需要构建的包,它使用软连接(符号链接,Symbolic Link)连接到存储在项目中的实际位置。这种方式使得包的安装非常快速,并且节约磁盘空间。
文件夹后有个回车的icon,这个代表当前这个文件是一个软链接文件。
软链接的设计既保证了不会出现幽灵依赖的问题,同时也能兼容 node 的寻找模块方式。
羞耻的提升:原则上幻影依赖不可以使用,但是可以添加配置使node_modules下的依赖扁平化,提升到 node_modules中
.npmrc
shamefully-hoist = true
pnpm硬链接(Hard Link)
硬链接是文件系统中的一个链接,它指向磁盘上的数据。
- pnpm 有个根目录来存储下载的包,一般都是保存在
user/.pnpm-store下 - pnpm 通过
硬链接的方式保证了相同的包不会被重复下载:比如说项目A安装了express@4.17.1,之后项目B中也安装express@4.17.1的时候是会被复用的,这两个项目中express文件指向的是同一个inode,新项目复用就会增加这个文件的硬链接个数
软链和硬链在 pnpm 中起着至关重要的作用。通过使用软链和硬链技术,pnpm 不仅避免了幽灵依赖的问题,还提高了包的复用率,节省了磁盘空间。这些特性使得 pnpm 在前端开发中成为了一个强大而高效的包管理工具。