关于包管理器Npm、Yarn和Pnpm的一些总结( 二 )


当我们使用npm3安装koa包时,它会首先检查该包所需的所有依赖项是否已经安装,如果没有安装,则会将这些依赖项直接安装到根目录下的node_modules目录中 。同时,npm3会使用符号链接将这些依赖项链接到需要使用它们的包的node_modules目录下 。

关于包管理器Npm、Yarn和Pnpm的一些总结

文章插图
 
 
通过使用符号链接,npm3可以实现依赖项的共享,从而避免了依赖项的重复安装和占用大量的磁盘空间 。此外,npm3还支持npm shrinkwrap命令,可以生成一个lockfile文件,记录每个包所使用的依赖项的精确版本号,从而避免了版本冲突和不兼容的问题 。
 
shrinkwrap 文件的作用是什么?
这个文件用于记录整个依赖树的结构和依赖包的版本信息,可以保证依赖包的版本稳定性和一致性 。
那么使用扁平化方案就能完美解决以上问题吗?当然不是 。
  • 幽灵依赖:在声明中没有使用dependencies中的依赖,代码中也可以进行reqiure引入 。没有在项目中进行显式依赖,如果别的包不再依赖这个包,就会导致代码因为依赖这个包,而没有进行安装,最终不能正常运行 。
  • 磁盘浪费:对于依赖包只会提升一个,存在多个版本时其余包同样得进行拷贝到各自node_modules下,依然会存在磁盘空间浪费 。
【关于包管理器Npm、Yarn和Pnpm的一些总结】什么是幽灵依赖?
在安装和使用某个第三方包时,该包依赖的其他依赖没有在它的js文件中显式引入的情况 。这些依赖可能在代码中被引用,但是没有被包含在软件包的package.json文件中 。这种情况被称为“幽灵依赖” 。
举个例子,假设有个项目需要依赖包 A 和 B,而这两个包都依赖于包 C,但是包 A 依赖于包 C 的版本 1.0.0,而包 B 依赖于包 C 的版本 2.0.0 。在 npm2 中,这两个版本的包 C 会被分别安装在 A 和 B 的 node_modules 目录下,不会产生冲突 。但在 npm3 中,这两个版本的包 C 可能会被安装在同一个 node_modules 目录下,这时候就会产生冲突,导致代码无法运行 。
关于包管理器Npm、Yarn和Pnpm的一些总结

文章插图
虽然在npm3提供了 npm dedupe 命令,可以是手动输入命令将重复的依赖项合并到顶层 node_modules 目录下,避免了幽灵依赖的问题 。但是好像并没有很智能 。
总的来说,npm3通过采用扁平化的依赖管理结构和符号链接机制,引入 shrinkwrap 文件实现了依赖项的共享和版本精确控制,并且减少了依赖项的嵌套层级和磁盘空间占用 。可以手动使用 dedupe 命令等方式,解决了 npm2 中出现的幽灵依赖问题,提高了包管理的效率和可靠性 。
pnpm针对上面遗留下的两个问题,pnpm横空出世,采用硬链接和符号链接来管理依赖项,以减少重复下载和占用空间,从而有效地解决幽灵依赖和磁盘浪费的问题 。
  • 基于内容寻址的文件系统来存储磁盘的文件
  • 不会重复安装同一个包,只在磁盘中写入一次,而后在使用的地方通过hardlink
  • 同包不同版本,也尽可能复用代码
link:也就是软硬连接,这是操作系统提供的机制 。
  • 硬连接就是同一个文件的不同引用
  • 软链接是新建一个文件,文件内容指向另一个路径
具体来说,当使用 pnpm 安装koa包的依赖项时,它会首先检查系统上是否已经安装了所需的依赖项 。如果已经安装,则 pnpm 将创建一个符号链接到该依赖项,而不是在当前项目中复制该依赖项 。这样就避免了重复下载和占用磁盘空间的问题 。
我们在命令行输入:
pnpm add koa
关于包管理器Npm、Yarn和Pnpm的一些总结

文章插图

关于包管理器Npm、Yarn和Pnpm的一些总结

文章插图
此外,pnpm 还支持不同的包引用方式,如路径引用和 git 仓库引用,这使得 pnpm 可以更快地安装依赖项并减少重复下载,从而提高开发效率和依赖项管理的可靠性 。通过将包从全局 store 进行硬链接到项目的虚拟 store 中,pnpm 可以避免多次拷贝文件和深度嵌套路径过长的问题,从而进一步减少磁盘空间的占用和提高性能 。
关于包管理器Npm、Yarn和Pnpm的一些总结


推荐阅读