網站導覽
目錄
資料夾
選擇 CLI 版本
目錄
說明
npm 會在您的電腦上放置各種東西。這是它的工作。
本文將告訴您它放置在哪裡。
tl;dr
- 本機安裝(預設):將資料放置在目前套件根目錄的
./node_modules
中。 - 全域安裝(使用
-g
):將資料放置在 /usr/local 或 node 安裝的任何位置。 - 如果您要
require()
,請將其安裝在本機。 - 如果您要在命令列上執行,請將其安裝在全域。
- 如果您需要同時安裝,請在兩個地方安裝,或使用
npm link
。
prefix 組態
預設 prefix
設定 為 node 安裝的位置。在大部分系統中,這是 /usr/local
。在 Windows 中,這是 %AppData%\npm
。在 Unix 系統中,由於 node 通常安裝在 {prefix}/bin/node
而不是 {prefix}/node.exe
,因此會高一層。
當 global
旗標設定時,npm 會將項目安裝到此 prefix。當未設定時,它會使用目前套件的根目錄,或如果不在套件中,則使用目前工作目錄。
Node 模組
套件會放置在 prefix
下的 node_modules
資料夾中。在本地安裝時,這表示您可以 require("packagename")
來載入其主要模組,或 require("packagename/lib/path/to/sub/module")
來載入其他模組。
在 Unix 系統上的全域安裝會轉到 {prefix}/lib/node_modules
。在 Windows 上的全域安裝會轉到 {prefix}/node_modules
(也就是沒有 lib
資料夾)。
範圍套件的安裝方式相同,但它們會群組在一起,放在相關 node_modules
資料夾的子資料夾中,該子資料夾的名稱是範圍前綴,加上 @ 符號,例如 npm install @myorg/package
會將套件放置在 {prefix}/node_modules/@myorg/package
。有關更多詳細資訊,請參閱 scope
。
如果您想 require()
套件,請在本地安裝它。
可執行檔
在全域模式中,可執行檔會連結到 Unix 上的 {prefix}/bin
,或直接連結到 Windows 上的 {prefix}
。確保路徑在您的終端的 PATH
環境中,才能執行它們。
在本地模式中,可執行檔會連結到 ./node_modules/.bin
,以便讓它們可供透過 npm 執行的腳本使用。(例如,這樣一來,當您執行 npm test
時,測試執行器就會在路徑中。)
手冊頁
在全域模式中,手冊頁會連結到 {prefix}/share/man
。
在本地模式中,不會安裝手冊頁。
不會在 Windows 系統上安裝手冊頁。
快取
請參閱 npm cache
。快取檔案儲存在 Posix 上的 ~/.npm
,或 Windows 上的 %LocalAppData%/npm-cache
。
這由 cache
設定 參數控制。
暫存檔案
預設情況下,暫存檔案會儲存在由 tmp
設定 指定的資料夾中,預設為 TMPDIR、TMP 或 TEMP 環境變數,或 Unix 上的 /tmp
和 Windows 上的 c:\windows\temp
。
暫存檔案會在這個根目錄下獲得每個程式執行階段的唯一資料夾,並在成功結束時刪除。
更多資訊
在本地安裝時,npm 會先嘗試尋找適當的 prefix
資料夾。這是為了讓 npm install foo@1.2.3
安裝到您套件的合理根目錄,即使您碰巧 cd
到其他資料夾。
從 $PWD 開始,npm 會向上瀏覽資料夾樹狀結構,檢查包含 package.json
檔案或 node_modules
資料夾的資料夾。如果找到此類資料夾,則將其視為執行 npm 指令的有效「目前目錄」。(此行為受到 git 在工作目錄中執行 git 指令時尋找 .git 資料夾的邏輯啟發,且與其類似。)
如果找不到套件根目錄,則使用目前資料夾。
當您執行 npm install foo@1.2.3
時,套件會載入快取,然後解壓縮到 ./node_modules/foo
。然後,foo 的任何相依套件也會以類似方式解壓縮到 ./node_modules/foo/node_modules/...
。
任何 bin 檔案都會連結到 ./node_modules/.bin/
,以便 npm 指令在需要時可以找到它們。
全域安裝
如果 global
設定 設為 true,則 npm 會「全域」安裝套件。
對於全域安裝,套件的安裝方式大致相同,但會使用上述資料夾。
循環、衝突和資料夾簡約
循環會使用節點模組系統的特性來處理,它會向上瀏覽目錄尋找 node_modules
資料夾。因此,在每個階段,如果套件已安裝在祖先 node_modules
資料夾中,則不會在目前位置安裝。
考慮上述情況,其中 foo -> bar -> baz
。假設除此之外,baz 還依賴於 bar,因此您會得到:foo -> bar -> baz -> bar -> baz ...
。但是,由於資料夾結構為:foo/node_modules/bar/node_modules/baz
,因此不需要將 bar 的另一個副本放入 .../baz/node_modules
中,因為當 baz 呼叫 require("bar")
時,它會取得安裝在 foo/node_modules/bar
中的副本。
此捷徑僅在多個巢狀 node_modules
資料夾中安裝完全相同的版本時使用。如果兩個「a」套件是不同版本,仍然有可能有 a/node_modules/b/node_modules/a
。但是,在不重複完全相同的套件多次的情況下,將永遠防止無限迴歸。
另一個最佳化方式是將相依項安裝在最高層級,也就是在地化的「目標」資料夾 (hoisting) 底下。從版本 3 開始,npm 預設會 hoist 相依項。
範例
考慮這個相依項圖
foo+-- blerg@1.2.5+-- bar@1.2.3| +-- blerg@1.x (latest=1.3.7)| +-- baz@2.x| | `-- quux@3.x| | `-- bar@1.2.3 (cycle)| `-- asdf@*`-- baz@1.2.3`-- quux@3.x`-- bar
在這個情況下,我們預期會看到這樣的資料夾結構 (所有相依項都 hoist 到最高層級)
foo+-- node_modules+-- blerg (1.2.5) <---[A]+-- bar (1.2.3) <---[B]| +-- node_modules| +-- baz (2.0.2) <---[C]+-- asdf (2.3.4)+-- baz (1.2.3) <---[D]+-- quux (3.2.0) <---[E]
由於 foo 直接相依於 bar@1.2.3
和 baz@1.2.3
,因此會將這些相依項安裝在 foo 的 node_modules
資料夾中。
即使 blerg 的最新版本是 1.3.7,但 foo 特別相依於版本 1.2.5。因此,會將此版本安裝在 [A]。由於 blerg 的父層安裝滿足了 bar 對 blerg@1.x
的相依項,因此不會在 [B] 下安裝另一個副本。
Bar [B] 也相依於 baz 和 asdf。由於它相依於 baz@2.x
,因此無法重複使用父層 node_modules
資料夾 [D] 中安裝的 baz@1.2.3
,而必須安裝自己的副本 [C]。為了最小化重複,npm 預設會將相依項 hoist 到頂層,因此 asdf 會安裝在 [A] 下。
在 bar 下方,baz -> quux -> bar
相依項會產生一個循環。但是,由於 bar 已在 quux 的祖先 [B] 中,因此不會在該資料夾中解壓另一個 bar 副本。同樣地,quux 的 [E] 資料夾樹是空的,因為它對 bar 的相依項已由安裝在 [B] 的父層資料夾副本滿足。
若要取得各個項目安裝位置的圖形細目,請使用 npm ls
。
發布
在發布時,npm 會在 node_modules
資料夾中尋找。如果該資料夾中的任何項目不在 bundleDependencies
陣列中,則不會將這些項目包含在封裝 tarball 中。
這允許封裝維護者在本地安裝他們的所有相依項 (和開發相依項),但只重新發布無法在其他地方找到的那些項目。請參閱 package.json
以取得更多資訊。