npm(Node Package Manager)
特点
- ✅ 默认包管理器,兼容性最好
- ✅ 简单易用,适合小型项目
- ✅ 支持
package-lock.json(锁定依赖版本)
npm 3.x之前的版本缺点
- ❌ 会有依赖过深导致找不到依赖的情况
- ❌ 相同的依赖重复下载,导致下载慢且占用内存空间大
下图 A/C/D 三个包若同时都依赖了B,npm 3.x之前会下载3次B。若B又有其他依赖,会导致依赖过深
node_modules/
├── A/
│ ├── node_modules/
│ │ └── B@1.0.0
│ └── package.json (依赖 B@1.0.0)
├── C/
│ ├── node_modules/
│ │ └── B@2.0.0
│ └── package.json (依赖 B@2.0.0)
└── D/
├── node_modules/
│ └── B@1.0.0
└── package.json (依赖 B@1.0.0)
npm 3.x之后的版本缺点(解决之前版本依赖过深且重复包导致占用体积大)
- ❌ 安装速度较慢
- ❌ 扁平化后,会有幻影依赖(package.json中没有声明,由于扁平化后,源码中引用了此依赖),可能会导致依赖版本问题和依赖丢失问题
下图 A/C/D 三个包若同时都依赖了B,npm 3.x之后 只会下载2次B,包会扁平化。
node_modules/
├── A/
├── B@1.0.0/
├── C/
├── B@2.0.0/
└── D/
举例说明npm 3.x之后幻影依赖导致的问题(以下工程使用npm管理包)
element-plus包依赖了dayjs包,由于npm 3.x之后对依赖的管理是扁平化,于是安装element-plus依赖的时候,就把dayjs包提升到node_modules一级目录,然后项目里就可以引入dayjs,并使用
import dayjs from 'dayjs'
const now = dayjs().format('YYYY-MM-DD')
package.json 并没有显示声明 dayjs 包,但是dayjs包提升到node_modules一级目录,就可以被直接使用。若有一天升级了element-plus版本,dayjs版本可能也会跟着自动升级,可能会导致dayjs版本改变导致项目出问题。另外若哪天element-plus删除了dayjs依赖,又会导致项目运行报错。
其实yarn根npm 3.x之后管理包的方式基本一致
pnpm
解决包依赖过深,相同的依赖重复下载导致体积大,幻影依赖的问题。
举例说明 pnpm 解决包依赖过深+幻影依赖的问题
element-plus同样的依赖dayjs包,这次使用pnpm下载后,dayjs包既没有出现在element-plus目录里面(npm 3.x之前),又没有直接出现在node_modules一级目录(npm 3.x之后)。通过软硬链接,dayjs包实际出现在.pnpm目录里面。这样就避免项目可以直接引用的问题
// pnpm管理后,由于package.json中没有显示声明,所以直接无法引用,这样就避免包升级或包丢失的问题
// 下面代码开发环境就会直接报错
import dayjs from 'dayjs'
const now = dayjs().format('YYYY-MM-DD')
pnpm后若项目里想使用dayjs包,须package.json中显示声明dayjs,并且pnpm安装。这样就算哪天element-plus去除了它里面的dayjs依赖,也不会影响项目的正常运行。
node_modules/
├── .pnpm/ # 所有依赖的硬链接存储在这里
│ ├── lodash@4.17.0/
│ └── lodash@4.17.20/
├── package-a/ # 符号链接到 .pnpm/package-a@1.0.0
└── package-b/ # 符号链接到 .pnpm/package-b@1.0.0