跳到主内容
版本:Next

常见问题

如果包存储在全局存储中,为什么我的 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 不会创建深层文件夹,它使用符号链接来创建依赖关系树结构。

尽管 pnpm 使用链接将依赖项放入 node_modules 文件夹,循环的符号链接已经被避免了,因为父包放置在其依赖项所在 node_modules 文件夹中。 所以 foo的依赖项不在 foo/node_modules 中,foo 其实和它 依赖项一起在 node_modules 中。

为什么使用硬链接? 为什么不直接创建到全局存储的符号链接?

一台机器上一个包在可以有不同的依赖集。

在项目 A foo@1.0.0 可以具有一个依赖被解析为 bar@1.0.0,但在项目 Bfoo 的依赖可能会被解析至 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

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.