常见问题
如果包存储在全局存储中,为什么我的 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 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
在下面的例子中,一个依赖在它自己的 deps 列表中没有 iterall
模块。
解决有问题的包缺少依赖项的最简单的解决方案是将 增加 iterall
作为我们项目的 package.json
中的依赖项。
您可以这样做,方法是通过 pnpm add iterall
安装它,并自动将它添加到您项目的 package.json
中。
"dependencies": {
...
"iterall": "^1.2.2",
...
}
解决方案3
解决方案之一是使用 hooks 将缺少的依赖项添加到包的 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
问题是 babel-traverse
被用于 inspectpack
, 然后被用于 webpack-dashboard
,但是 babel-traverse
没有在 inspectpack
的 package.json
中。 它仍然与 npm
和 yarn
兼容,因为它们构建的平铺的 node_modules
结构。
解决方案是创建一个 .pnpmfile.cjs
,内容如下:
module.exports = {
hooks: {
readPackage: (pkg) => {
if (pkg.name === "inspectpack") {
pkg.dependencies['babel-traverse'] = '^6.26.0';
}
return pkg;
}
}
};
创建 .pnpmfile.cjs
后,仅删除 pnpm-lock.yaml
- 不需要 删除 node_modules
,因为 pnpm 挂钩仅影响模块解析。 然后,重建依赖项 & 它应该可以工作。