跳到主要内容

pnpm

  • 支持monorepo

    • 替代lerna
  • 速度快

  • 节省磁盘空间

    • 1、如果你对同一依赖包需要使用不同的版本,则仅有 版本之间不同的文件会被存储起来。例如,如果某个依赖包包含 100 个文件,其发布了一个新 版本,并且新版本中只有一个文件有修改,则pnpm update 只需要添加一个 新文件到存储中,而不会因为一个文件的修改而保存依赖包的 所有文件

    一个包的不同版本,pnpm 可以复用之前版本的代码。只会下载新版本的新文件,会复用之前版本的文件

    • 2、所有文件都保存在硬盘上的统一的位置。当安装软件包时, 其包含的所有文件都会硬链接自此位置,而不会占用 额外的硬盘空间。这让你可以在项目之间方便地共享相同版本的 依赖包。
  • 可以替代npm、yarn

硬连接就是同一个文件的不同引用,而软链接是新建一个文件,文件内容指向另一个路径

pnpm是如何解决幽灵依赖问题​

  • pnpm采用了软链接的方式去引用依赖
  • 通过软链接可以把 .pnpm的包软链接到当前项目 node_modules中,而不需要将包的源代码拷贝到当前项目,这种方式可以避免重复包拷贝和占用磁盘空间
    • 节省磁盘空间: 因为不需要在每个项目中复制依赖,所以节省了大量的磁盘空间。

pnpm为何速度快?​

  • 下载安装依赖的时候,pnpm会先检查store目录,会从store目录硬链接到项目中,而不会重新安装依赖

  • 一个包的不同版本,pnpm 可以复用之前版本的代码。只会下载新版本的新文件,会复用之前版本的文件

pnpm 为何节省空间?​

  • 1、它解决了 npm/yarn 平铺 node_modules 带来的依赖项重复的问题 (doppelgangers)
  • 2、所有文件都保存在硬盘上的统一的位置。当安装软件包时, 其包含的所有文件都会硬链接自此位置,而不会占用 额外的硬盘空间。这让你可以在项目之间方便地共享相同版本的 依赖包。
  • 3、通过软链接可以把 .pnpm的包软链接到当前项目 node_modules中,而不需要在每个项目中复制依赖

常用命令​

  • pnpm add: 安装依赖包
  • pnpm dlx 【类似npx】
  • pnpm run :运行scrips脚本,可简写
    • 注意简写【仅适用于那些不与已有的 pnpm 命令相同名字的脚本】
    • 比如如果scripts命令中存在deploy,简写执行pnpm deploy会有问题,pnpm会以为执行内置的命令,正确是 pnpm run deploy
  • pnpm install
  • pnpm -F : 选择指定的包
  • pnpm publish : 发布
    • pnpm publish -F 可以指定某个包发布
    • pnpm publish -r 可以一键发布所有包
  • pnpm -r : 每个项目中运行命令 【recursive递归】
  • pnpm i -w :只在根目录的node_modules安装 【-w 指根目录】
  • pnpm exec : 执行当前项目的依赖
  • pnpm update: 根据指定的范围更新软件包的最新版本
  • pnpm -C <path> : 在<path> 中启动 pnpm ,而不是当前的工作目录。
  • pnpm -w : 在工作区根目录中启动pnpm
  • pnpm deploy: 部署命令
    • 将指定项目的代码与依赖以可移植的形式打包到目标目录
    • 如pnpm deploy --filter=@project/app dist
      • 将 @project/app 的 项目文件(包括 package.json、构建产物、配置等)完整复制到 dist 目录。默认包含所有文件,但可通过 package.json 的 files 字段控制包含内容

查看pnpm配置

  • pnpm config get proxy : 查看代理
  • pnpm config delete proxy:需要取消代理
  • pnpm store path: 获取pnpm 的 store 目录所在的位置

pnpm配置代理镜像

如配置electron镜像

bash
pnpm config set electron_mirror https://mirrors.huaweicloud.com/electron/
pnpm config set electron_builder_binaries_mirror https://mirrors.huaweicloud.com/electron-builder-binaries/

pnpm的工作空间(Workspace)​

pnpm 内置了对单一存储库(也称为多包存储库、多项目存储库或单体存储库)的支持, 你可以创建一个 workspace 以将多个项目合并到一个仓库中

引用 workspace 包​

  • 在 workspace 中有一个名为foo 的包, 通常你会像这样引用:"foo": "workspace:*"
  • 相对路径引入:bar中可能有foo的依赖:"foo": "workspace:../foo"

当执行发布命令之后,pnpm publish, 会动态替换workspace参数

publishConfig问题​

  • 表示当publish发布命令的之后,要覆盖的字段
bash
{
"name": "foo",
"version": "1.0.0",
"main": "src/index.ts",
"publishConfig": {
"main": "lib/index.js",
"typings": "lib/index.d.ts"
}
}

将发布为:

json
{
"name": "foo",
"version": "1.0.0",
"main": "lib/index.js",
"typings": "lib/index.d.ts"
}

.npmrc常用配置​

  • auto-install-peers
    • 当值为true 时,将自动安装任何缺少的非可选同级依赖关系。

pnpm在软链接和硬链接作用是什么?​

总结:

  • pnpm在 硬链接的作用可以在不同项目之间共享pnpm的store目录
  • pnpm在 软链接的作用 项目的node_modules这个文件夹中创建符号链接,包之间通过软链接的方式来相互引用依赖包,来复用相同版本的包依赖
    • 如果项目A依赖于项目B中的某个包,pnpm会创建一个软链接,将该包链接到项目A的node_modules中,而不是复制整个包。这可以节省磁盘空间

项目的所有的依赖都是从全局 store 硬链接到了 node_modules/.pnpm 下,然后之间通过软链接来相互依赖

硬链接:

.pnpm 中存放着所有的包。最终硬链接指向指向全局pnpm 仓库里的store目录下。

也就是说,我们所有的包,最终都以硬链接的形式,最终都在全局 pnpm/store 中,可以使得不同的项目从全局 store 寻找到同一个依赖,大大节省了磁盘空间。

  • 硬链接的作用可以在不同项目之间共享store文件

与软链接相比,硬链接的好处是它创建的链接可以被看作是源文件的副本,对应的文件节点数会增加,但它不会占用额外的磁盘空间,因为硬链接和源文件共享磁盘上的同一个数据块,只有在硬链接被删除时,才会释放对应的数据块

软链接:

pnpm 的软链接就是将 node_modules 里的文件软链接到对应的 .pnpm/[package_name]@version/node_modules/[package_name] 中。【pnpm软链接就是将node_mudules的文件软链接到对应的pnpm某个包的某个版本】

  • 软链接的设计保证不会出现幽灵依赖的问题
  • 通过软链接可以把 .pnpm的包软链接到当前项目 node_modules中,而不需要将包的源代码拷贝到当前项目,这种方式可以避免重复包拷贝和占用磁盘空间
    • 通过软链接来相互依赖
  • 软链接的作用是将一个包的源代码链接到多个项目中,避免在每个项目中都拷贝一份源代码

node_modules/.pnpm 可以理解为虚拟 store

npm2 是通过嵌套的方式管理 node_modules 的,会有同样的依赖复制多次的问题。

npm3+ 和 yarn 是通过铺平的扁平化的方式来管理 node_modules,解决了嵌套方式的部分问题,但是引入了幽灵依赖的问题,并且同名的包只会提升一个版本的,其余的版本依然会复制多次。

为什么会出现复制多次?

  • 多个包之间难免会有公共的依赖,这样嵌套的话,同样的依赖会复制很多次,会占据比较大的磁盘空间

pnpm 则是用了另一种方式,不再是复制了,而是都从全局 store 硬链接

到 node_modules/.pnpm,然后之间通过软链接来组织依赖关系。

补充知识点:

  • 软链接:
  • 软链接,也称为符号链接,它创建一个特殊类型的文件,其中包含指向另一个文件或目录的路径
  • 如果源文件被删除了,软链接会保留下来,但是会失效
  • 移除源文件不会移除快捷方式
  • 软链接会占用磁盘空间
  • 硬链接:
  • 硬链接是文件系统中的一种特殊链接,它允许一个文件存在于多个位置,但在磁盘上只占用一个存储空间
  • 移除源文件不会影响硬链接
  • 移除硬链接不会影响源文件
  • 如果源文件被删除,它的内容依然通过硬链接存在
  • 硬链接文件的任何更改都会影响到源文件
  • 硬链接并不占用额外的磁盘空间

为什么硬链接并不占用额外的磁盘空间?而软链接会占用磁盘空间

  • 硬链接:在操作系统内部创建了一个指向另一个文件的新文件名,硬链接并不包含文件路径信息,而是直接指向另一个文件的 inode【即文件索引节点,包含了文件的元数据和实际数据块的位置信息】

    • 如果源文件被删除,硬链接会一直存在,除非你明确地将它删除
  • 软链接会包含文件的路径,当你使用软链接时,操作系统会读取软链接文件中包含的路径,然后转到真正的文件操作

    • 如果源文件被删除,软链接仍然存在,但是它将失效,因为它所指向的文件已经不存在
    • 软链接的大小取决于软链接文件中包含的路径信息的长度

如果源文件被删除,为什么硬链接仍然有效?

  • 如果源文件被删除,硬链接仍然有效,因为它只是对另一个文件的新文件名的引用。即使源文件被删除,硬链接仍然可以指向另一个文件的 inode,并且仍然可以使用硬链接访问源文件的数据

如果源文件被删除了,为什么软链接会失效?

  • 如果源文件被删除,软链接仍然存在,但是它将失效,因为它所指向的文件已经不存在。这意味着,如果你尝试使用软链接访问源文件,操作系统将会返回一个错误消息,表示文件不存在。

pnpm 弊端​

调试问题

所有项目引用的包都在全局一个地方,如果想对某个包进行调试,其他项目正好引用了,本地运行也会收到影响。