常見問題
如果套件都存在全域的儲存區了,為什麼我的 node_modules
資料夾仍佔用硬碟空間?
pnpm 會透過 硬連結的方式連結全域存儲到專案資料夾下的 node_modules
資料夾。 硬連結會指向硬碟上原始檔所在的同一位置。 因此,例如,如果您的項目中有 foo
作為依賴項並且它佔用 1MB 空間,那麼它看起來就像它在項目的 node_modules
文件夾中占用了與全局存儲相同的 1MB 空間。 但是,這 1MB 是硬碟上兩個不同位置的相同空間 。 所以 foo
總共只占用 1MB,而不是 2MB。
有關這個主題的更多資訊:
pnpm 可以在 Windows 上執行嗎?
一句話:是的。 詳細回答:在 Windows 上使用符號連結會造成許多問題,但 pnpm 有一個暫時的解決方法。 對於 Windows,我們用junctions替代。
但是巢狀 node_modules
的方式不適用於 Windows?
之前的 npm 版本因巢狀內嵌了所有 node_modules
發生問題 (請參閱此問題)。 However, pnpm does not create deep folders, it stores all packages flatly and uses symbolic links to create the dependency tree structure.
What about circular symlinks?
Although pnpm uses linking to put dependencies into node_modules
folders, circular symlinks are avoided because parent packages are placed into the same node_modules
folder in which their dependencies are. So foo
's dependencies are not in foo/node_modules
, but foo
is in node_modules
together with its own dependencies.
為什麼使用硬連結? 為什麼不直接 symlink 至全域的儲存區?
一個包在一台機器上可以有不同的依賴集。
In project A foo@1.0.0
can have a dependency resolved to bar@1.0.0
, but in project B the same dependency of foo
might resolve to bar@1.1.0
; so, pnpm hard links foo@1.0.0
to every project where it is used, in order to create different sets of dependencies for it.
Direct symlinking to the global store would work with Node's --preserve-symlinks
flag, however, that approach comes with a plethora of its own issues, so we decided to stick with hard links. For more details about why this decision was made, see this issue.
pnpm 可以在多磁碟機、檔案系統上運作嗎?
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. 請參見 Issue #712 以了解詳細資訊。
pnpm 在下列兩種情形中的行為不同
已指定儲存區路徑
如果已透過 store config 指定了儲存區路徑,只有在其他硬碟上的專案會導致複製套件。
如果您在硬碟 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
中。 這是由平鋪的 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.