常見問題集
如果套件儲存在全域儲存庫中,為何我的 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
未在 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 hooks 僅會影響模組解析。然後,重新建置相依項,它應該就可以正常運作了。