常见问题
如果包存储在全局存储中,为什么我的 node_modules
使用了磁盘空间?
pnpm 创建从全局存储到项目下 node_modules
文件夹的 硬链接。 硬链接指向磁盘上原始文件所在的同一位置。 例如,如果您的项目有 foo
作为依赖者 并且它占用了 1MB 的空间。 然后看起来它将占用了 项目的 node_modules
文件夹和全局的 存储空间相同的空间。 但是,该 1MB 是磁盘上两个不同位置的相同空间 。 所以 foo
总共占用 1MB,而不是 2MB。
获取有关此主题的更多信息:
能用于Windows吗?
短回答:当然 长答案:在 Windows 上使用符号链接至少可以说是有问题的,但是,pnpm 有一个解决方法。 对于 Windows,我们用junctions替代。
但是嵌套的 node_modules
组织方式与 Windows 兼容吗?
npm 的早期版本由于嵌套了所有 node_modules
(参见 这个 issue). 但是,pnpm 不会创建深层文件夹,它使用符号链接来创建依赖关系树结构。
循环 symlinks 呢?
尽管 pnpm 使用链接将依赖项放入 node_modules
文件夹,循环的符号链接已经被避免了,因为父包放置在其依赖项所在 node_modules
文件夹中。 所以 foo
的依赖项不在 foo/node_modules
中,foo
其实和它 依赖项一起在 node_modules
中。
为什么使用硬链接? 为什么不直接创建到全局存储的符号链接?
一台机器上一个包在可以有不同的依赖集。
在项目 A foo@1.0.0
可以具有一个依赖被解析为 bar@1.0.0
,但在项目 B 中 foo
的依赖可能会被解析至 bar@1.1.0
; 因此,pnpm 硬链接 foo@1.0.0
到每个使用它的项目,以便为其创建不同的依赖项集。
直接软链至全局存储与 Node 的 --preserve-symlinks
标志一起使用是可行的,但是,该方法附带了个自己的问题,因此我们决定使用硬链接。 有关为何作出决定的详情,请参阅 这个 issue。
Pnpm 是否可以跨多个驱动器或文件系统工作?
包存储应与安装的位置处于同一驱动器和文件系统上,否则,包将被复制,而不是被链接。 这是由于硬链接的工作方式带来的一个限制,因为一个文件系统上的文件无法寻址另一个文件系统中的位置。 更多详细信息请参阅 issue #712。
pnpm 在以下两种情况下的功能有所不同:
存储路径已指定
如果存储路径是通过 存储配置指定的,则存储与项目间的复制行为将会发生在不同的磁盘上。
如果您在磁盘 A
上执行 pnpm install
,则 pnpm 存储必须位于磁盘 A
。 如果 pnpm 存储位于磁盘 B
,则所有需要的包将被直接复制到项目位置而不是链接。 这严重抑制了 pnpm 的存储和性能优势。
存储路径未指定
如果未设置存储路径,则会创建多个存储(每个驱动器或文件系统一个)。
如果安装在磁盘 A
上运行,则存储将在 A
的文件系统根目录下的 .pnpm-store
下被创建。 如果后续安装在磁盘 B
上运行,则将会在 B
上的 .pnpm-store
处创建一个独立的存储。 项目仍将保持 pnpm 的优势,但每个驱动器可能有冗余包。
pnpm
代表什么?
pnpm
代表 performant(高性能的) npm
。 @rstacruz想出了这个名字。
pnpm
无法在 <你的项目>中使用 ?
在大多数情况下,这意味着被使用的依赖项之一没有在 package.json
中被声明的。 It is a common mistake caused by flat node_modules
. 如果发生这种情况,这是依赖项中的错误,应修复依赖项。 但这可能需要时间,因此 pnpm 支持额外的解决方法来使有问题的包工作。
解决方案1
In case there are issues, you can use the node-linker=hoisted
setting. This creates a flat node_modules
structure similar to the one created by npm
.
解决方案2
In the following example, a dependency does not have the iterall
module in its own list of deps.
The easiest solution to resolve missing dependencies of the buggy packages is to add iterall
as a dependency to our project's package.json
.
You can do so, by installing it via pnpm add iterall
, and will be automatically added to your project's package.json
.
"dependencies": {
...
"iterall": "^1.2.2",
...
}
解决方案3
One of the solutions is to use hooks for adding the missing dependencies to the package's package.json
.
An example was Webpack Dashboard which wasn't working with pnpm
. It has since been resolved such that it works with pnpm
now.
It used to throw an error:
Error: Cannot find module 'babel-traverse'
at /node_modules/inspectpack@2.2.3/node_modules/inspectpack/lib/actions/parse
The problem was that babel-traverse
was used in inspectpack
which was used by webpack-dashboard
, but babel-traverse
wasn't specified in inspectpack
's package.json
. It still worked with npm
and yarn
because they create flat node_modules
.
The solution was to create a .pnpmfile.cjs
with the following contents:
module.exports = {
hooks: {
readPackage: (pkg) => {
if (pkg.name === "inspectpack") {
pkg.dependencies['babel-traverse'] = '^6.26.0';
}
return pkg;
}
}
};
After creating a .pnpmfile.cjs
, delete pnpm-lock.yaml
only - there is no need to delete node_modules
, as pnpm hooks only affect module resolution. Then, rebuild the dependencies & it should be working.