npm yarn pnpm

99 阅读3分钟

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管理包)

image.png element-plus包依赖了dayjs包,由于npm 3.x之后对依赖的管理是扁平化,于是安装element-plus依赖的时候,就把dayjs包提升到node_modules一级目录,然后项目里就可以引入dayjs,并使用

image.png

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 解决包依赖过深+幻影依赖的问题

image.png 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