pnpm: 更快更节省磁盘的包管理器

什么是 pnpm ?

pnpm 是 npm 的替代者,命名是“Performant NPM”的简写,它更快、更节省空间,并且解决了 npm 的一些固有问题。在这篇文章中,我将会讨论它是如何工作的,并说明为什么 pnpm 是 npm 或 yarn 的完美替代品。

使用 npm 或者 yarn 的问题:

  • 如果你有 100 个项目,并且所有项目都有一个相同的依赖包,那么你在硬盘上就需要保存 100 份该相同依赖包的副本,非常浪费空间。
  • 使用扁平化的 node_modules,扁平化的依赖关系导致了一些问题,比如:
    • 可以引用没在 package.json 文件中声明的依赖。比如你安装了 express,它有一个 debug 的依赖包,npm install 后的目录结构如下图,此时你可以在项目代码里面引用 debug package。如果未来 express 更新了 debug 大版本或者将其删除,会对你的工程代码造成很大的影响。

    • 同一个项目中如果引用了不同版本的 package A,node_modules 文件夹里面会下载多份 package A, 比如: B 使用 A@1.0.0, 而 C 使用了 A@2.0.0, 此时就会下载两份 package A。

pnpm 怎么解决这些问题?

pnpm 使用硬链接和软链接来维护 node_modules 的结构, (硬链接和软链接有什么区别?请参考上一篇文章),还是使用上面express的例子。

上图显示了使用 pnpm 后项目文件的目录结构。你会发现工程代码无法访问到 debug 包了,因为它不在 node_modules 第一级目录。pnpm 创建了一个名为".pnpm "的文件夹,包含了所有模块的硬链接。
如果看一下express/4.0.0,express模块是一个指向全局pnpm-store的硬链接,debug 模块也是如此。

下图是实际的 pnpm-store 结构,它包含了这些 package, 所有下载的依赖都保存在这里。当你下载一个依赖项时,pnpm 首先检查该依赖项是否存在于这个仓库中。如果它在仓库中找到了该依赖项,pnpm 会通过创建一个硬链接来获取它。

由于这种方法,如果同样的软件包已经为另一个项目安装了,pnpm 就会重复使用这些软件包。

相对于 npm 或 yarn 的优势:

节省大量的磁盘空间。

如上所示,pnpm 使用了一个内容可寻址的文件系统来存储磁盘上的软件包和依赖项。这意味着相同的软件包不会被重复下载。即使是同一个软件包的不同版本,pnpm也会智能地重复使用最大的代码。如果一个包的版本 1.0.0 有 100 个文件,而版本 2.0.0 只多了一个文件,那么 pnpm 不会为版本 2.0.0 写 101 个文件;相反,它将创建一个硬链接到原来的 100 个文件,只新建一个新文件。

安装软件包更快。

从下图可以看到,用 pnpm 安装依赖的速度明显优于 npm 和 yarn。

内置了对 monorepo 的支持

目前 monorepo 可能还是老牌工具 lerna 使用的比较多,pnpm 内置了对 monorepo 的支持,更为简洁易用,具体可参考官方文档 workspaces

从 npm/yarn 迁移到 pnpm

如果你的项目使用了 npm 或 yarn,迁移到 pnpm 不是很困难,下面是npm、yarn和pnpm之间的命令比较。

npm command Yarn command pnpm equivalent
npm install yarn pnpm install
npm install [pkg] yarn add [pkg] pnpm add [pkg]
npm uninstall [pkg] yarn remove [pkg] pnpm remove [pkg]
npm update yarn upgrade pnpm update
npm list yarn list pnpm list
npm run [scriptName] yarn [scriptName] pnpm [scriptName]
npx [command] yarn dlx [command] pnpm dlx [command]
npm exec yarn exec [commandName] pnpm exec [commandName]
npm init [initializer] yarn create [initializer] pnpm create [initializer]
posted @ 2022-12-14 21:17  WinjayYu  阅读(390)  评论(0编辑  收藏  举报