npm script 是記錄在 package.json
中的 scripts
字段中的一些自定義腳本,使用自定義腳本,用戶能夠將一些項目中經常使用的命令行記錄在 package.json
不須要每次都要敲一遍。node
必須開發者經常須要使用如下命令來統計項目中的代碼行數:webpack
find src -name "*.js" | xargs cat | wc -l
開發者能夠將其寫入 package.json
中:git
"scripts":{ "lines": "find src -name \"*.js\" | xargs cat | wc -l", }
之後開發者只須要執行 npm run lines
就能夠了,而不須要再去寫那麼長的命令行,這能夠大幅提升效率。須要注意的是,由於命令是寫在 json 文件中的,有些特字符須要進行轉譯,好比上面的雙引號。web
PATH
npm scripts 不是簡簡單單地執行 shell 語句而已,在執行以前它會將 node_modules/.bin/
加入到環境變量 PATH
中,因此在 npm scripts 中能夠直接使用那些存在於 node_modules/.bin/
中的可執行文件。shell
不少使用 mocha 做爲測試框架的項目中都有這麼一個 npm scriptnpm
"scripts":{ "test": "mocha" }
mocha 並無全局安裝,它的命令行工具存在於 node_modules/.bin/
中,之因此可以訪問到它,正是由於 npm 背後的這一操做才使得這樣的命令可以正常執行,在 npm script 執行完成後,會從 PATH
中移除。json
在執行 npm run test
(後面會看到這能夠簡寫爲 npm test
) 的時候就等同於:gulp
./node_modules/.bin/mocha
對於上面的腳本 "test": "mocha"
若是但願給 mocha 傳入一些選項,好比但願執行:框架
mocha --reporter spec
須要這樣執行 npm test:ssh
npm test -- --reporter spec
須要使用兩個短線將選項隔開,或者將選項直接寫在 package.json
中:
"scripts":{ "test": "mocha --reporter spec" }
在 shell 中傳入的參數都要使用 --
隔開,這個 --
被視做 npm run 命令參數的結束,--
後面的內容都會原封不動地傳給運行的命令。
在 npm script 中存在兩個鉤子,pre
和 post
,就拿上面的 lines 腳原本說,它的鉤子腳本就是 prelines
和 postlines
"scripts":{ "prelines": "node prelines.js" "lines": "find src -name \"*.js\" | xargs cat | wc -l", "postlines": "node postlines" }
執行 npm run lines
,會先執行 prelines
再執行 lines
以後再執行 postlines
。
還有一些 script 會在模塊安裝,發佈,卸載等不一樣的生命週期被執行。
prepublish, publish, postpublish:發佈模塊
preinstall, install, postinstall:安裝模塊
preuninstall, uninstall, postuninstall:卸載模塊
preversion, version, postversion:在使用 npm version 修改版本號的時候執行
pretest, test, posttest:執行 npm test
的時候
prestop, stop, poststop:執行 npm stop
的時候
prestart, start, poststart:執行 npm start
的時候
prerestart, restart, postrestart:執行 npm restart
的時候
這些 script 會在不一樣的時刻自動被執行,這也是爲何 npm run test
能夠簡寫爲 npm test
的緣由了,在執行 npm test
的時候會以次執行 pretest
、test
和 posttest
,固然了,若是沒有指定 pretest
和 posttest
,會默默地跳過。
還有 npm restart
這個命令比較叼,它不僅僅執行 prerestart
, restart
, postrestart
這三個,而是按下面的順序來執行:
prerestart
prestop
stop
poststop
restart
prestart
start
poststart
postrestart
在執行 npm script 的時候還能夠訪問到一些特殊的環境變量,經過 process.env.npm_package_xxx
能夠得到到 package.json
中的內容。好比 process.env.npm_package_name
能夠得到到 package.json
中 name
的值 "sv"
。
{ "name": "sv", "version": "1.3.0", "description": "", "main": "index.js", "repository": { "type": "git", "url": "git+ssh://git@gitlab.com/wy-ei/sv.git" } }
經過 process.env.npm_package_repository_type
能夠拿到值 "git"
。
另外能夠經過 process.env.npm_config_xxx
來拿到 npm config 中的值。好比經過 process.env.npm_config_user_email
能夠拿到 user.email
的值。
還有一個比較特殊的環境變量 process.env.npm_lifecycle_event
在執行不一樣的 npm script 的時候這個值是不一樣的,好比執行 npm run build
的時候,這個值爲 build
,經過判斷這個變量,將一個腳本使用在不一樣的 npm script 中。
使用任何腳本語言編寫的 npm script 均可以拿到環境變量,好比在 shell 中要想拿到只須要使用 $npm_config_user_email
就行了。不一樣的腳本須要使用其自身獲取環境變量的方法來讀取環境變。
另外,這些環境變量只能在執行 npm script 的時候拿到,正常執行的 node 腳本是獲取不到的。
在 npm script 經常用到一些模塊中的可執行程序,好比 eslint,webpack 等,那麼要如何來本身編寫一個命令行工具能,讓它能夠在 npm script 中被調用。
新建文件 cli.js
,寫入須要的邏輯。
console.log("This article is Awesome, isn't it?");
package.json
的 bin 字段中指定命令行文件名稱和路徑{ "bin": { "cli": "./cli.js" } }
當用戶安裝之後,經過 ./node_modules/.bin/cli
執行,會報錯,緣由是目前 shell 不知道使用什麼解釋器來執行這些代碼,爲此須要在腳本上方指定解釋器。
#!usr/bin/env node console.log("This article is Awesome, isn't it?");
上面這一行在全部腳本文件中均可以看到,它叫作 SheBang 或者 HashBang,詳見 Shebang_(Unix)),這行代碼是告訴 shell 使用何種解釋器來執行代碼。usr/bin/env
是一個程序,usr/bin/env node
會找到當前 PATH 中的 node 來解釋後面的代碼。
有了這三步,就開發出了一個 node 的命令行工具。當用戶安裝這個模塊的時候,npm 會在 node_modules/.bin/
中建立文件,名爲 package.json
中的 bin 指定的命令名,並連接至對應的腳本。此後就能夠在 npm script 中使用它了。
多說兩句,將上面的 #!usr/bin/env node
寫入 JavaScript 文件第一行,不會報錯。由於這是一個 UNIX 世界都認識的東西。經過 chmod +x cli.js
,你可使用 ./cli.js
直接執行它,由於這一行已經告訴 shell 使用 node 來執行它了。
早在今年 3 月,在網上看到不少帖子,涌現出一個觀點,要使用 npm script 來代替 gulp 這樣的構建工具,現在看到 npm script 的功能確實強大,利用 node 和 shell 咱們可以寫出一些很實用的腳本,來解決手頭的問題,並不必定須要利用 gulp,grunt 這樣的東西。據統計,在 2015 年 gulp 以絕對的優點佔據着 task runner 使用率第一的位置,而在 2016 年 npm script 的使用率提高的很是快。
不管如何,npm script 老是會出如今你天天的工做中,願本文能助你搞懂 npm script,讓 npm script 幫助你加快開發效率。