npm
npm2的时候,它的node_modules是层级嵌套的。每一个依赖都会有自己的node_modules。但是多个包之间难免会有公共的依赖,这样会占据比较大的内存空间。并且windows最长的文件描述符是260多个字符,这样层级嵌套的话会超过最大的长度限制的。然后出现了yarn,解决了这个问题
node_modules - package-A -- node_modules --- package-B ----- node_modules ------ package-C -------- some-really-really-really-long-file-name-in-package-c.js
cnpm
相对于 npm 而言, cnpm 的下载速度要快很多。 cnpm 更快,是因为淘宝将国外服务器的内容,先请求到了自己国内的服务器上,这样我们使用cnpm的时候下载的依赖就是从国内服务器上下载过来的,速度相对快很多。
官网上说:“这是一个完整 npmjs.org镜像,你可以用此代替官方版本,同步频率目前为 10分钟 一次以保证尽量与官方服务同步。”
yarn
让所有依赖都在同一个层级,大多数包是没有嵌套的,但是少部分还是存在嵌套关系。
为什么会出现嵌套
因为一个包可能会有多个版本,提升的话只能提升一个,所以后面再遇到相同包的不同版本,依然还是用嵌套的模式。然后yarn还实现了yarn.lock来锁定版本的功能,不过npm也改进了。
扁平化方案的缺陷
最主要的一个问题是幽灵依赖,也就是你明明没有声明在 dependencies 里的依赖,但在代码里却可以 require 进来。
这个也很容易理解,因为都铺平了嘛,那依赖的依赖也是可以找到的。
但是这样是有隐患的,因为没有显式依赖,万一有一天别的包不依赖这个包了,那你的代码也就不能跑了,因为你依赖这个包,但是现在不会被安装了。
这就是幽灵依赖的问题。
而且还有一个问题,就是上面提到的依赖包有多个版本的时候,只会提升一个,那其余版本的包不还是复制了很多次么,依然有浪费磁盘空间的问题。
pnpm
performant npm速度快,节省磁盘空间的软件包管理工具
pnpm 在依赖包管理方式上完全舍弃了 npm 的那一套,而是巧妙利用 symbol link 和 hard link 做出了自己的创新。
哪些公司使用pnpm
在了解pnpm的设计之前,我们先来了解一下什么是软链接,什么是硬链接
软链接软链接(符号链接):保存的其实是一个文件的路径
- 软链接其实是一类特殊的文件
- 其包含有一条以绝对路径或相对路径的形式指向其他文件或者目录的引用
硬链接
- 硬链接是电脑文件系统中的多个文件平等的共享同一个文件存储单元
- 删除一个文件名字后,还可以用其他名字继续访问该文件
当使用npm或者yarn的时候,如果你有100个项目,并且所有项目都有一个相同的依赖包,那么,在你的硬盘上面就会保存100份该相同的依赖包副本
但是使用pnpm的时候,依赖包将会被存放在同一个位置,所以
- 如果依赖的版本相同,那么磁盘上就会只有这一个依赖包的文件
- 如果同一依赖包使用的是不同的版本,则只会将版本不同的文件保存起来
- 所有文件都保存在硬盘上的统一的位置
当安装软件包的时候,其包含的所有文件都会硬链接到此位置,而不会占用额外的硬盘空间。同时也可以让你方便的共享相同版本的依赖包
非扁平化
官方的原理图:pnpm 从全局 store 硬连接到 node_modules/.pnpm,然后之间通过软链接来组织依赖关系。
我们从官方文档的例子来看,比如我安装了一个bar:^1.0.0
的依赖。首先在目录外面,我会显示一个bar:^1.0.0
的依赖,然后实际的存储位置放在.pnpm
这个文件里面。 bar
直接通过硬链接,指向磁盘内的一块空间,同时bar
又会依赖foo
,这时候发现foo
依赖已经安装过了,所以直接通过软链接指向外面就可以了