包管理工具 npm 和 yarn 都是很优秀的,但也存在一些潜在的问题。当相互依赖包的数量达到一定的量级时,不仅会占用大量的磁盘空间,还会大大影响包的拉取速度。
所以需要更优秀的 pnpm 包管理工具来进行优化,从而打造一个高效的工程化环境
工具 npm2 的工作原理
-
假设场景
有三个模块:A、B 和 C。A 依赖于 B 的 v1.0 版本,C 依赖于 B 的 v2.0 版本
-
终端结果
可以通过
npm ls查看所有依赖项关系也可以通过
npm ls --depth=0查看主要依赖项 -
工作原理
以嵌套的方式安装所有依赖项
-
痛点问题
当包中创建了太深的依赖树时,在
Windows上的目录路径过长,就会导致无法删除当一个包被多个依赖项依赖时,它会被多次复制粘贴并生成多份文件,就会导致磁盘空间浪费
-
延伸知识
Windows下文件路径有260字符长度限制,可以通过调用Unicode版的Windows API函数来绕过限制
工具 npm3+ 的工作原理
-
假设场景
有两个模块:A 和 B。A 依赖于 B
有三个模块:A、B 和 C。A 依赖于 B 的 v1.0 版本,C 依赖于 B 的 v2.0 版本
-
终端结果
可以通过
npm ls查看所有依赖项关系也可以通过
npm ls --depth=0查看主要依赖项 -
工作原理
以依赖扁平化的方式安装所有依赖项,减轻嵌套导致的深层树和冗余
但是,顶级依赖是唯一的,且只能有一个版本,所以不能将顶级依赖的其它版本也安装为顶级依赖项。这种情况下,
npm v3将默认为npm v2行为并将新的、不同的模块版本依赖项嵌套在需要它的模块下来进行处理 -
与 npm2 的主要区别
目录结构中的位置不再预测依赖项的类型(主要、次要等)
依赖关系的解决取决于安装顺序,或者安装顺序将改变 node_modules 目录树结构
-
痛点问题
幻影依赖:模块可以访问
package.json中未注册的包,开发者也可以直接引入使用,影响安全性扁平化算法本身的复杂性很高,对于多层次嵌套的文件耗时明显增加
工具 pnpm 的工作原理
-
软链接和硬链接
软链接(symbolic link) 可理解为指向源文件的指针,它是单独的一个文件,仅仅只有几个字节,它拥有独立的
inode硬链接(hard link) 与源文件同时指向一个物理地址,它与源文件共享储存数据,它俩拥有相同的
inode -
节约磁盘空间并提升安装速度
使用
pnpm时,依赖会被存储在内容可寻址的存储中。文件内容发生变化后将会按需更新,而不是全量复制整个新版本包的内容;所有文件都存储在硬盘上的某一位置,当包被安装时,包里的文件会硬链接到这一位置,而不会占用额外的磁盘空间
允许跨项目地共享同一版本的依赖,速度比其它包管理工具快两到三倍
-
创建非扁平化的 node_modules 文件夹
使用软链接的方式将项目的直接依赖添加进模块文件夹的根目录
-
常用命令
npm install pnpm -g pnpm安装 pnpm add <pkg> 安装软件包到 dependencies pnpm add -D <pkg> 安装软件包到 devDependencies pnpm add -g <pkg> 全局安装软件包 pnpm install 或 pnpm i 下载项目所有依赖项 pnpm update 或 pnpm up 遵循 package.json 指定的范围更新所有的依赖项 pnpm update -g <pkg> 从全局更新一个依赖包 pnpm remove <pkg> 从项目的 package.json 中删除相关依赖项 pnpm remove -D <pkg> 仅删除开发环境 devDependencies 中的依赖项 pnpm remove <pkg> -g 从全局删除一个依赖包 pnpm run <script> 或 pnpm <script> 运行脚本
工具 pnpm 性能总结
-
快速
pnpm是同类工具速度的将近2倍 -
高效
node_modules中的所有文件均克隆或硬链接自单一存储位置 -
支持单体仓库
pnpm内置了对单个源码仓库中包含多个软件包的支持 -
权限严格
pnpm创建的node_modules默认并非扁平结构,因此代码无法对任意软件包进行访问