跳到主要內容
版本:9.x

常見問題集

如果套件儲存在全域儲存庫中,為何我的 node_modules 資料夾會使用磁碟空間?

pnpm 從全域儲存庫建立 硬連結 至專案的 node_modules 資料夾。硬連結指向原始檔案在磁碟上的相同位置。因此,例如,如果專案中 foo 為相依性,且佔用 1MB 空間,則看起來它在專案的 node_modules 資料夾中佔用 1MB 空間,且在全域儲存庫中佔用相同大小的空間。然而,這 1MB 是磁碟上 相同的空間,從兩個不同的位置存取。因此,總而言之,foo 佔用 1MB,而非 2MB。

有關此主題的更多資訊

它能在 Windows 上執行嗎?

簡短回答:是。長篇回答:在 Windows 上使用符號連結至少來說是有問題的,不過,pnpm 有個解決方法。對於 Windows,我們使用 連接點 來代替。

但是嵌套的 node_modules 方法與 Windows 不相容?

早期版本的 npm 因為嵌套所有 node_modules 而有問題(請參閱 這個問題)。不過,pnpm 沒有建立深層資料夾,它將所有套件平坦儲存,並使用符號連結來建立相依性樹狀結構。

儘管 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 旗標一起作用,不過,這種方法會帶來許多它自己的問題,因此我們決定堅持使用硬連結。有關為何做出此決定的更多詳細資訊,請參閱 這個問題

pnpm 是否可以在一個 Btrfs 分割區的不同子區中運作?

儘管 Btrfs 不允許在單一分割區中不同子區卷之間進行跨裝置硬連結,但它允許 reflinks。因此,pnpm 利用 reflinks 在這些子區卷之間共享資料。

pnpm 是否可在多個磁碟機或檔案系統中運作?

套件儲存庫應與安裝位於同一個磁碟機和檔案系統中,否則套件將會被複製,而不是連結。這是由於硬連結運作方式的限制,一個檔案系統中的檔案無法存取另一個檔案系統中的位置。請參閱 Issue #712 以取得更多詳細資訊。

pnpm 在以下 2 種情況中運作方式不同

指定儲存庫路徑

如果透過 儲存庫設定 指定儲存庫路徑,則會在儲存庫與任何位於不同磁碟中的專案之間進行複製。

如果您在磁碟機 A 上執行 pnpm install,則 pnpm 儲存庫必須位於磁碟機 A 上。如果 pnpm 儲存庫位於磁碟機 B 上,則所有必要的套件將直接複製到專案位置,而不是連結。這會嚴重影響 pnpm 的儲存和效能優勢。

未指定儲存庫路徑

如果未設定儲存庫路徑,則會建立多個儲存庫(每個磁碟機或檔案系統一個)。

如果在磁碟機 A 上執行安裝,則會在檔案系統根目錄下的 A .pnpm-store 中建立儲存庫。如果稍後在磁碟機 B 上執行安裝,則會在 B 上的 .pnpm-store 中建立獨立的儲存庫。專案仍會維持 pnpm 的優勢,但每個磁碟機可能會有重複的套件。

pnpm 代表什麼?

pnpm 代表 performant npm@rstacruz 想出這個名字。

pnpm 無法與 <YOUR-PROJECT-HERE> 搭配使用?

在多數情況下,這表示其中一個相依項需要未在 package.json 中宣告的套件。這是由扁平的 node_modules 所造成的常見錯誤。如果發生這種情況,表示相依項有錯誤,且應該修復相依項。這可能需要一些時間,因此 pnpm 支援解決方案,以讓有錯誤的套件正常運作。

解決方案 1

如果遇到問題,您可以使用 node-linker=hoisted 設定。這會建立一個扁平的 node_modules 結構,類似於 npm 所建立的結構。

解決方案 2

在以下範例中,相依項沒有在它自己的相依項清單中包含 iterall 模組。

解決有錯誤套件中遺失相依項最簡單的方法,是iterall 新增為我們專案的 package.json 中的相依項

您可以透過 pnpm add iterall 安裝它,它會自動新增至您專案的 package.json 中。

  "dependencies": {
...
"iterall": "^1.2.2",
...
}

解決方案 3

其中一個解決方案是使用 hooks 將遺失的相依項新增至套件的 package.json 中。

其中一個範例是 Webpack Dashboard,它無法與 pnpm 搭配使用。它後來已獲得解決,現在可以與 pnpm 搭配使用。

它會擲回一個錯誤

Error: Cannot find module 'babel-traverse'
at /node_modules/inspectpack@2.2.3/node_modules/inspectpack/lib/actions/parse

問題在於 babel-traverse 用於 inspectpack 中,而 inspectpack 又用於 webpack-dashboard,但 babel-traverse 未在 inspectpackpackage.json 中指定。它仍然可以與 npmyarn 搭配使用,因為它們會建立扁平的 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 hooks 僅會影響模組解析。然後,重新建置相依項,它應該就可以正常運作了。