網站導覽
目錄
指令碼
選擇 CLI 版本
目錄
說明
package.json
檔案的 "scripts"
屬性支援多個內建指令碼和其預設的生命週期事件,以及任意指令碼。這些都可以透過執行 npm run-script <stage>
或簡寫的 npm run <stage>
來執行。對於這些指令碼,也會執行具有相符名稱的 前置 和 後置 指令碼 (例如 premyscript
、myscript
、postmyscript
)。相依性的指令碼可以使用 npm explore <pkg> -- npm run <stage>
來執行。
前置和後置指令碼
若要為在 package.json
的 "scripts"
區段中定義的任何腳本建立「pre」或「post」腳本,只要建立另一個 名稱相符 的腳本,並在開頭加上「pre」或「post」即可。
{"scripts": {"precompress": "{{ executes BEFORE the `compress` script }}","compress": "{{ run command to compress files }}","postcompress": "{{ executes AFTER `compress` script }}"}}
在此範例中,npm run compress
會如說明所述執行這些腳本。
生命週期指令碼
有些特殊生命週期腳本只會在特定情況下發生。這些腳本會在 pre<event>
、post<event>
和 <event>
腳本之外發生。
prepare
、prepublish
、prepublishOnly
、prepack
、postpack
、dependencies
prepare (自 npm@4.0.0
起)
-
在封裝套件之前執行,例如在
npm publish
和npm pack
期間執行 -
在沒有任何引數的情況下執行本機
npm install
-
在
prepublish
之後,但在prepublishOnly
之前執行 -
注意:如果透過 git 安裝的套件包含
prepare
腳本,則會在封裝並安裝套件之前,安裝其dependencies
和devDependencies
,並執行 prepare 腳本。 -
自
npm@7
起,這些腳本會在背景執行。若要查看輸出,請使用--foreground-scripts
執行。
prepublish (已棄用)
- 在
npm publish
期間不會執行,但在npm ci
和npm install
期間會執行。請參閱下方以取得更多資訊。
prepublishOnly
- 在準備並封裝套件之前執行,僅在
npm publish
中執行。
prepack
- 在封裝 tarball 之前執行(在「
npm pack
」、「npm publish
」以及安裝 git 相依項時執行)。 - 注意:「
npm run pack
」與「npm pack
」不同。「npm run pack
」是使用者定義的任意腳本名稱,而「npm pack
」是 CLI 定義的指令。
postpack
- 在產生 tarball 之後,但在將其移至最終目的地之前執行(如果有的話,發布不會在本地儲存 tarball)
dependencies
- 在對
node_modules
目錄進行任何修改操作之後執行,如果發生變更。 - 不會在全域模式中執行
準備和預發佈
棄用注意事項:prepublish
自 npm@1.1.71
起,npm CLI 已同時為 npm publish
和 npm install
執行 prepublish
腳本,因為這是一種為套件做好使用準備的便利方式(以下部分說明一些常見的使用案例)。實際上,這也證明 非常令人困惑。自 npm@4.0.0
起,已推出一個新事件 prepare
,用於保留這項既有行為。已新增一個新事件 prepublishOnly
,作為過渡策略,讓使用者避免現有 npm 版本令人困惑的行為,而且僅在 npm publish
上執行(例如,最後一次執行測試,以確保它們處於良好狀態)。
請參閱 https://github.com/npm/npm/issues/10074,深入了解這項變更的理由,並進一步閱讀。
使用案例
如果您需要在套件使用前執行作業,而且作業不依賴目標系統的操作系統或架構,請使用 prepublish
腳本。這包括以下任務
- 將 CoffeeScript 原始碼編譯成 JavaScript。
- 建立 JavaScript 原始碼的縮小版本。
- 擷取套件將使用的遠端資源。
在 prepublish
時間執行這些作業的優點是,它們可以在單一位置執行一次,從而降低複雜性和變異性。此外,這表示
- 您可以依賴
coffee-script
作為devDependency
,因此您的使用者不需要安裝它。 - 您不需要在套件中包含縮小程式,以減少使用者的檔案大小。
- 您不需要依賴使用者在目標機器上擁有
curl
或wget
或其他系統工具。
相依性
只要 npm
指令造成 node_modules
目錄變更,就會執行 dependencies
指令碼。在變更套用後,且 package.json
和 package-lock.json
檔案更新後,才會執行此指令碼。
生命週期操作順序
npm cache add
prepare
npm ci
preinstall
install
postinstall
prepublish
preprepare
prepare
postprepare
這些指令碼會在模組實際安裝到 node_modules
之後,依序執行,其間不會執行任何內部動作
npm diff
prepare
npm install
執行 npm install -g <pkg-name>
時,也會執行這些指令碼
preinstall
install
postinstall
prepublish
preprepare
prepare
postprepare
如果您的套件根目錄中有一個 binding.gyp
檔案,而且您尚未定義自己的 install
或 preinstall
指令碼,npm 會預設 install
指令,透過 node-gyp rebuild
使用 node-gyp 編譯
這些指令碼會從 <pkg-name>
的指令碼執行
npm pack
prepack
prepare
postpack
npm publish
prepublishOnly
prepack
prepare
postpack
publish
postpublish
npm rebuild
preinstall
install
postinstall
prepare
prepare
僅在目前目錄為符號連結時執行(例如連結套件)
npm restart
如果已定義 restart
指令碼,則執行這些事件,否則如果存在,則執行 stop
和 start
,包括其 pre
和 post
迭代)
prerestart
restart
postrestart
npm run <user defined>
pre<user-defined>
<user-defined>
post<user-defined>
npm start
prestart
start
poststart
如果套件根目錄中有一個 server.js
檔案,則 npm 會將 start
指令預設為 node server.js
。在這種情況下,prestart
和 poststart
仍會執行。
npm stop
prestop
stop
poststop
npm test
pretest
test
posttest
npm version
preversion
version
postversion
關於缺乏 npm uninstall
指令碼的注意事項
雖然 npm v6 有 uninstall
生命週期指令碼,但 npm v7 沒有。移除套件的原因可能有很多,目前沒有明確的方法可以為指令碼提供足夠的內容以使其有用。
移除套件的原因包括
- 使用者直接移除此套件
- 使用者移除依賴套件,因此此依賴項也正在移除
- 使用者移除依賴套件,但其他套件也依賴此版本
- 此版本已與另一個版本合併為重複版本
- 等
由於缺乏必要的內容,uninstall
生命周期腳本尚未實作,且無法運作。
使用者
當 npm 以 root 身分執行時,腳本總是會以工作目錄擁有者的有效 uid 和 gid 執行。
環境
套件腳本在環境中執行,其中提供了許多關於 npm 設定和目前處理程序狀態的資訊。
路徑
如果您依賴定義可執行腳本的模組,例如測試套件,則這些可執行檔會加入到 PATH
中,以執行腳本。因此,如果您的 package.json 具有以下內容
{"name": "foo","dependencies": {"bar": "0.1.x"},"scripts": {"start": "bar ./test"}}
則您可以執行 npm start
來執行 bar
腳本,該腳本會在 npm install
時匯出到 node_modules/.bin
目錄中。
package.json 變數
package.json 欄位會附加到 npm_package_
前置詞。因此,例如,如果您在 package.json 檔案中有 {"name":"foo", "version":"1.2.5"}
,則您的套件腳本會將 npm_package_name
環境變數設定為「foo」,並將 npm_package_version
設定為「1.2.5」。您可以在程式碼中使用 process.env.npm_package_name
和 process.env.npm_package_version
存取這些變數,其他欄位也一樣。
請參閱 package.json
,以進一步瞭解套件組態。
目前的生命週期事件
最後,npm_lifecycle_event
環境變數會設定為正在執行的循環階段。因此,您可以使用單一腳本,針對處理程序的不同部分進行切換,具體取決於目前正在發生的事情。
物件會按照此格式扁平化,因此如果您在 package.json 中有 {"scripts":{"install":"foo.js"}}
,則您會在腳本中看到以下內容
process.env.npm_package_scripts_install === "foo.js"
範例
例如,如果您的 package.json 包含以下內容
{"scripts": {"install": "scripts/install.js","postinstall": "scripts/install.js"}}
然後 scripts/install.js
將會在生命週期的安裝和安裝後階段被呼叫。由於 scripts/install.js
會執行兩個不同的階段,因此在這種情況下,最好查看 npm_lifecycle_event
環境變數。
如果您想執行 make 指令,您可以這麼做。這運作良好
{"scripts": {"preinstall": "./configure","install": "make && make install","test": "make test"}}
結束
指令碼會透過將該行傳遞為指令碼引數給 sh
來執行。
如果指令碼以 0 以外的代碼結束,則會中止該程序。
請注意,這些指令碼檔案不必是 Node.js 或甚至是 JavaScript 程式。它們只需要是某種可執行檔即可。
最佳實務
- 除非您真的這麼想,否則不要以非零錯誤代碼結束。如果失敗是輕微的,或者只會阻止某些選用功能,那麼最好只印出警告並成功結束。
- 盡量不要使用指令碼來執行 npm 可以為您執行的動作。請詳閱
package.json
,以查看您可以透過適當地描述您的套件來指定和啟用所有事項。一般來說,這將導致更強健且一致的狀態。 - 檢查 env 以確定要放置的位置。例如,如果
npm_config_binroot
環境變數設定為/home/user/bin
,則不要嘗試將可執行檔安裝到/usr/local/bin
。使用者可能因為某個原因而這樣設定。 - 不要使用「sudo」為您的指令碼指令加上前置詞。如果由於某些原因需要 root 權限,則會失敗並顯示該錯誤,而使用者會對有問題的 npm 指令使用 sudo。
- 不要使用
install
。請使用.gyp
檔案進行編譯,並使用prepare
執行其他任何動作。您幾乎不應該明確設定 preinstall 或 install 指令碼。如果您正在執行此操作,請考慮是否有其他選項。唯一有效的install
或preinstall
指令碼用途是編譯,而編譯必須在目標架構上執行。 - 指令碼會從套件資料夾的根目錄執行,而不管在呼叫
npm
時目前的作業目錄為何。如果您希望您的指令碼根據您所在的子目錄使用不同的行為,您可以使用INIT_CWD
環境變數,它會儲存您在執行npm run
時所在的完整路徑。