npm ls -g
npm root -g
npm bin -g
npm link
:全局安裝未發布的套件npm link
:本地安裝已全局連結的套件npm link
:取消連結npx
:在 npm 套件中執行 bin 腳本,而無需安裝
package.json
屬性 "bin"
讓 npm 套件可以指定它提供的 Shell 腳本(更多資訊,請參閱 §14「建立跨平台 Shell 腳本」)。如果我們安裝此類套件,Node.js 會確保我們可以從命令列存取這些 Shell 腳本(所謂的bin 腳本)。在本章中,我們將探討兩種安裝具有 bin 腳本的套件的方法
在套件中本地安裝具有 bin 腳本的套件表示將其安裝為套件內的依賴項。這些腳本只能在該套件內存取。
在套件中全局安裝具有 bin 腳本的套件表示將其安裝在「全局位置」,以便可以在任何地方存取這些腳本,無論是目前的使用者或系統的所有使用者(視 npm 的設定而定)。
我們將探討所有這些含意的內容,以及如何在安裝 bin 腳本後執行它們。
套件 cowsay
具有下列 package.json
屬性
"bin": {
"cowsay": "./cli.js",
"cowthink": "./cli.js"
},
若要全域安裝此套件,我們使用 npm install -g
npm install -g cowsay
注意事項:在 Unix 上,我們可能必須使用 sudo
(我們很快就會學到如何避免這樣做)
sudo npm install -g cowsay
在那之後,我們可以在命令列中使用 cowsay
和 cowthink
命令。
請注意,只有 bin 腳本可全域使用。當 Node.js 在 node_modules
目錄中查詢裸模組指定項時,套件會被忽略。
npm ls -g
我們可以檢查哪些套件已全域安裝,以及安裝在哪裡
% npm ls -g
/usr/local/lib
├── corepack@0.12.1
├── cowsay@1.5.0
└── npm@8.15.0
在 Windows 上,安裝路徑為 %AppData%\npm
,例如
>echo %AppData%\npm
C:\Users\jane\AppData\Roaming\npm
npm root -g
macOS 上的結果
% npm root -g
/usr/local/lib/node_modules
Windows 上的結果
>npm root -g
C:\Users\jane\AppData\Roaming\npm\node_modules
npm bin -g
npm bin -g
會告訴我們 npm 在何處全域安裝 shell 腳本。它還會確保 shell PATH 中有該目錄。
macOS 上的結果
% npm bin -g
/usr/local/bin
% which cowsay
/usr/local/bin/cowsay
Windows 命令殼層上的結果
>npm bin -g
C:\Users\jane\AppData\Roaming\npm
>where cowsay
C:\Users\jane\AppData\Roaming\npm\cowsay
C:\Users\jane\AppData\Roaming\npm\cowsay.cmd
沒有檔案副檔名的可執行檔 cowsay
適用於基於 Unix 的 Windows 環境,例如 Cygwin、MinGW 和 MSYS。
Windows PowerShell 會傳回此路徑以供 gcm cowsay
C:\Users\jane\AppData\Roaming\npm\cowsay.ps1
npm 的安裝前置詞決定套件和 bin 腳本安裝在何處。
這是 macOS 上的安裝前置詞
% npm config get prefix
/usr/local
因此
/usr/local/lib/node_modules
/usr/local/bin
這是 Windows 上的安裝前置詞
>npm config get prefix
C:\Users\jane\AppData\Roaming\npm
因此
C:\Users\jane\AppData\Roaming\npm\node_modules
C:\Users\jane\AppData\Roaming\npm
在本節中,我們將探討變更套件全域安裝位置的兩種方法
變更套件全域安裝位置的一種方法是變更 npm 安裝前置詞。
Unix
mkdir ~/npm-global
npm config set prefix '~/npm-global'
Windows 命令殼層
mkdir "%UserProfile%\npm-global"
npm config set prefix "%UserProfile%\npm-global"
Windows PowerShell
mkdir "$env:UserProfile\npm-global"
npm config set prefix "$env:UserProfile\npm-global"
組態資料會儲存到主目錄中的 .npmrc
檔案。
從現在開始,全域安裝會新增到我們剛剛指定的目錄中。
之後,我們仍然必須將 npm bin -g
目錄新增到我們的 shell PATH,這樣我們的 shell 才能找到我們全域安裝的 bin 腳本。
變更 npm 前綴的缺點:如果我們告訴 npm 自行升級,它現在也會安裝在新位置。
Node.js 版本管理員讓我們可以同時安裝多個版本的 Node.js,並在它們之間切換。熱門的版本管理員包括
若要在本地(安裝到套件中)安裝 npm 登錄檔套件,例如 cowsay
,我們會執行下列動作
cd my-package/
npm install cowsay
這會將下列資料新增到 package.json
"dependencies": {
"cowsay": "^1.5.0",
···
}
此外,套件會下載到下列目錄
my-package/node_modules/cowsay/
在 Unix 上,npm 會為 bin 腳本新增這些符號連結
my-package/node_modules/.bin/cowsay -> ../cowsay/cli.js
my-package/node_modules/.bin/cowthink -> ../cowsay/cli.js
在 Windows 上,npm 會將這些檔案新增到 my-package\node_modules\.bin\
cowsay
cowsay.cmd
cowsay.ps1
cowthink
cowthink.cmd
cowthink.ps1
沒有副檔名的檔案是針對 Unix-based Windows 環境(例如 Cygwin、MinGW 和 MSYS)的腳本。
npm bin
會告訴我們在本地安裝的 bin 腳本位於何處,例如
% npm bin
/Users/john/my-package/node_modules/.bin
注意:在本地,套件總是安裝在 package.json
檔案旁邊的 node_modules
目錄中。如果目前目錄中不存在後者,npm 會在祖先目錄中搜尋它,並在那裡安裝套件。若要查看 npm 會在何處在本地安裝套件,我們可以使用指令 npm root
,例如(Unix)
% cd $HOME
% npm root
/Users/john/node_modules
John 的家目錄中沒有 package.json
,但 npm 無法在祖先目錄中安裝任何東西,這就是 npm root
顯示這個目錄的原因。在目前位置在本地安裝套件會導致建立 package.json
,並照常進行安裝。
(本小節中的所有指令都在 my-package
目錄中執行。)
我們可以從 shell 如下執行 cowsay
./node_modules/.bin/cowsay Hello
在 Unix 上,我們可以設定一個輔助程式
alias npm-exec='PATH=$(npm bin):$PATH'
然後,下列指令會起作用
npm-exec cowsay Hello
我們也可以將套件腳本新增到 package.json
{
···
"scripts": {
"cowsay": "cowsay"
},
···
}
現在,我們可以在 shell 中執行這個指令
npm run cowsay Hello
這會起作用,因為 npm 會暫時將下列項目新增到 Unix 上的 $PATH
/Users/john/my-package/node_modules/.bin
/Users/john/node_modules/.bin
/Users/node_modules/.bin
/node_modules/.bin
在 Windows 上,類似的項目會新增到 %Path%
或 $env:Path
C:\Users\jane\my-package\node_modules\.bin
C:\Users\jane\node_modules\.bin
C:\Users\node_modules\.bin
C:\node_modules\.bin
下列指令會列出套件腳本執行期間存在的環境變數及其值
npm run env
在套件中,可以使用 npx 存取 bin 腳本
npx cowsay Hello
npx cowthink Hello
稍後會進一步說明 npx。
有時,我們有一個尚未發布或永遠不會發布的套件,而且想要安裝它。
npm link
:安裝未發佈套件至全域假設我們有一個未發佈的套件,其名稱為 @my-scope/unpublished-package
,儲存在目錄 /tmp/unpublished-package/
中。我們可以透過以下方式讓它在全域中可用
cd /tmp/unpublished-package/
npm link
如果我們這樣做
npm 會新增一個符號連結至全域 node_modules
(由 npm root -g
傳回)——例如
/usr/local/lib/node_modules/@my-scope/unpublished-package
-> ../../../../../tmp/unpublished-package
在 Unix 上,npm 也會從全域 bin 目錄(由 npm bin -g
傳回)新增一個符號連結至每個 bin 腳本。該連結並非直接連結,而是透過全域 node_modules
目錄
/usr/local/bin/my-command
-> ../lib/node_modules/@my-scope/unpublished-package/src/my-command.js
在 Windows 上,它會新增 3 個常見腳本(透過相對路徑參照全域 node_modules
中的連結套件)
C:\Users\jane\AppData\Roaming\npm\my-command
C:\Users\jane\AppData\Roaming\npm\my-command.cmd
C:\Users\jane\AppData\Roaming\npm\my-command.ps1
由於連結套件的參照方式,套件中的任何變更都會立即生效。變更時無需重新連結。
若要檢查全域安裝是否成功,我們可以使用 npm ls -g
列出所有已安裝的全域套件。
npm link
:安裝已連結至全域的套件至本機在我們將未發佈的套件安裝至全域後(請參閱前一個小節),我們可以選擇將它安裝至我們的其中一個套件(可以是已發佈或未發佈)
cd /tmp/other-package/
npm link @my-scope/unpublished-package
這會建立以下連結
/tmp/other-package/node_modules/@my-scope/unpublished-package
-> ../../../unpublished-package
預設情況下,未發佈的套件不會新增為 package.json
的相依性。其背後的原因是 npm link
通常用於暫時使用註冊表套件的未發佈版本——這不應顯示在相依性中。
npm link
:取消連結取消本機連結
cd /tmp/other-package/
npm uninstall @my-scope/unpublished-package
取消全域連結
cd /tmp/unpublished-package/
npm uninstall -g
安裝未發佈套件至本機的另一種方法是使用 npm install
並透過本機路徑(而非套件名稱)參照它
cd /tmp/other-package/
npm install ../unpublished-package
這有兩個影響。
首先,會建立以下符號連結
/tmp/other-package/node_modules/@my-scope/unpublished-package
-> ../../../unpublished-package
其次,會新增一個相依性至 package.json
"dependencies": {
"@my-scope/unpublished-package": "file:../unpublished-package",
···
}
這種安裝未發佈套件的方法也適用於全域
cd /tmp/unpublished-package/
npm install -g .
my-package/
。它們會複製至目錄 my-package/.yalc
,且 file:
或 link:
相依性會新增至 package.json
。relative-deps
支援 package.json
中的 "relativeDependencies"
,如果存在,則會覆寫一般相依性。與 npm link
和本機路徑安裝不同
relative-deps
也有助於保持本地安裝的相關依賴項及其原始依賴項同步。
npx link
是 npm link
的更安全版本,除了其他好處之外,它不需要全球安裝。npx
:在未安裝 npm 套件的情況下執行 bin 腳本npx 是與 npm 捆綁在一起的 shell 命令,用於執行 bin 腳本。
它最常見的用法是
npx <package-name> arg1 arg2 ...
此命令會在 npx 快取中安裝名稱為 package-name
的套件,並執行與該套件同名的 bin 腳本,例如
npx cowsay Hello
這表示我們可以在不先安裝 bin 腳本的情況下執行它們。npx 最適合一次性呼叫 bin 腳本,例如,許多架構都提供 bin 腳本來設定新專案,而這些腳本通常會透過 npx 執行。
npx 第一次使用套件後,該套件就會出現在其快取中,後續呼叫的速度也會快很多。不過,我們無法確定套件會在快取中停留多久。因此,npx 無法取代全球或本地安裝 bin 腳本。
如果套件附帶的名稱與其套件名稱不同的 bin 腳本,我們可以像這樣存取它們
npx --package=<package-name> <bin-script> arg1 arg2 ...
例如
npx --package=cowsay cowthink Hello
npx 的快取位在哪裡?
在 Unix 中,我們可以透過以下命令找出
npx --package=cowsay node -p \
"process.env.PATH.split(':').find(p => p.includes('_npx'))"
它會傳回類似以下的的路徑
/Users/john/.npm/_npx/8f497369b2d6166e/node_modules/.bin
在 Windows 中,我們可以使用 (將一行分成兩行)
npx --package=cowsay node -p
"process.env.Path.split(';').find(p => p.includes('_npx'))"
它會傳回類似以下的路徑 (將單一路徑分成兩行)
C:\Users\jane\AppData\Local\npm-cache\_npx\
8f497369b2d6166e\node_modules\.bin
請注意,npx 的快取與 npm 用於安裝模組的快取不同
$HOME/.npm/_cacache/
$HOME/.npm/_npx/
$env:UserProfile\AppData\Local\npm-cache\_npx\
$env:UserProfile\AppData\Local\npm-cache\_cacache\
兩個快取的父目錄可以透過以下方式確定
npm config get cache
有關 npm 快取的更多資訊,請參閱 npm 文件。
與 npx 快取相反,資料永遠不會從 npm 快取中移除,只會新增。我們可以在 Unix 上透過以下方式檢查其大小
du -sh $(npm config get cache)/_cacache/
在 Windows PowerShell 上
DiskUsage /d:0 "$(npm config get cache)\_cacache"