常见问题
如果包存储在全局存储中,为什么我的 node_modules
使用了磁盘空间?
pnpm 创建从全局存储到项目下 node_modules
文件夹的 硬链接。 硬链接指向磁盘上原始文件所在的同一位置。 因此,例如,如果您的项目中 foo
并且它占用 1MB 的空间,那么看起来它在项目的 node_modules
文件夹中占用了与全局存储相同的 1MB 的空间。 但是,该 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。
Does pnpm work across different subvolumes in one Btrfs partition?
While Btrfs does not allow cross-device hardlinks between different subvolumes in a single partition, it does permit reflinks. As a result, pnpm utilizes reflinks to share data between these subvolumes.
Does pnpm work across multiple drives or filesystems?
The package store should be on the same drive and filesystem as installations, otherwise packages will be copied, not linked. This is due to a limitation in how hard linking works, in that a file on one filesystem cannot address a location in another. See Issue #712 for more details.
pnpm functions differently in the 2 cases below:
存储路径已指定
If the store path is specified via the store config, then copying occurs between the store and any projects that are on a different disk.
If you run pnpm install
on disk A
, then the pnpm store must be on disk A
. If the pnpm store is located on disk B
, then all required packages will be directly copied to the project location instead of being linked. This severely inhibits the storage and performance benefits of pnpm.
存储路径未指定
If the store path is not set, then multiple stores are created (one per drive or filesystem).
If installation is run on disk A
, the store will be created on A
.pnpm-store
under the filesystem root. If later the installation is run on disk B
, an independent store will be created on B
at .pnpm-store
. The projects would still maintain the benefits of pnpm, but each drive may have redundant packages.
What does pnpm
stand for?
pnpm
stands for performant npm
. @rstacruz came up with the name.
pnpm
does not work with <YOUR-PROJECT-HERE>?
In most cases it means that one of the dependencies require packages not declared in package.json
. It is a common mistake caused by flat node_modules
. If this happens, this is an error in the dependency and the dependency should be fixed. That might take time though, so pnpm supports workarounds to make the buggy packages work.
解决方案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.