npm run 命令解析
在vue和react項目中,我們常常用到npm run dev命令來起本地服務,那么npm run dev到底做了什么?
package.json文件中的字段script的每一個屬性都是一個自定義的腳本命令,npm run 其實執行了package.json中的script腳本
下面的例子,我們以vue-cli3腳手架搭建的項目為例說明,所以當我們輸入命令npm run serve命令,底層相當執行vue-cli-service serve --port 8055命令
// package.json
"scripts": {
"serve": "vue-cli-service serve --port 8055",
"build": "vue-cli-service build",
"build:test": "vue-cli-service build --mode test",
"build:beta": "vue-cli-service build --mode beta",
"lint": "vue-cli-service lint",
"inspect-old": "vue-cli-service inspect --mode production > webpack.inspect.js",
"inspect": "vue inspect --mode production",
"inspectwebpack": "vue inspect --mode production > output.js"
}
知識點總結
npm run如果不加任何參數,直接運行,會列出package.json里面所有可以執行的腳本命令(script字段里面的內容)。
npm start可以運行是為了方便開發者使用,npm start會執行scripts里的start字段。 如果沒有start字段則執行node server.js。
This runs an arbitrary command specified in the package's "start" property of its "scripts" object. If no "start" property is specified on the "scripts" object, it will run node server.js.
執行原理
使用npm run script執行腳本的時候都會創建一個shell,然后在shell中執行指定的腳本。
這個shell會將當前項目的可執行依賴目錄(即node_modules/.bin)添加到環境變量path中,當執行之后再恢復原樣。就是說腳本命令中的依賴名會直接找到node_modules/.bin下面的對應腳本,而不需要加上路徑,所以scripts字段里面調用命令時不用加上路徑,這就避免了全局安裝NPM模塊
執行順序
'&' 並行執行順序,同時執行
"dev":"node test.js & webpack"
'&&'繼發順序,執行前面之后才可以執行后面
"dev":"node test.js && webpack"
順序鈎子
"predev":"node test_one.js",
"dev":"node test_two.js",
"postdev":"node test_three.js"
當執行 npm run dev 的時候默認就會執行
npm run predev && npm run dev && npm run postdev
四個可以簡寫的腳本執行命令
npm start === npm run start
npm stop === npm run stop
npm test === npm run test
npm restart === npm run stop && npm run restart && npm run start
使用package.json內部變量
通過npm_package_前綴,npm腳本可以拿到npm的內部變量
// package.json
{
"name":"zhy",
"test":"node test.js"
}
test.js:
console.log(process.env.npm_package_name) //zhy
node_modules/.bin文件夾內容解析
下面是vue-cli3搭建的項目node_modules/.bin文件夾下面的文件名
eslint
eslint.cmd
lessc
lessc.cmd
uuid
uuid.cmd
vue-cli-service
vue-cli-service.cmd
對於一個npm包,有兩個可執行文件,沒有后綴名的是是對應unix系的shell腳本,.cmd文件對應的是windows bat腳本,內容都是用node執行一個js文件
// vue-cli-service.cmd文件內容
// windows bat腳本
@IF EXIST "%~dp0\node.exe" (
"%~dp0\node.exe" "%~dp0\..\_@vue_cli-service@3.12.1@@vue\cli-service\bin\vue-cli-service.js" %*
) ELSE (
@SETLOCAL
@SET PATHEXT=%PATHEXT:;.JS;=;%
node "%~dp0\..\_@vue_cli-service@3.12.1@@vue\cli-service\bin\vue-cli-service.js" %*
)
這里是windows的cmd中的語法
~dp0指執行腳本的當前目錄,這句話的意思是如果當前目錄下有node.exe,就用node.exe執行... ...webpack.js文件 %*是指執行bat時命令中輸入的后續參數
否則 @SETLOCAL設置本次批處理命令中的環境變量
PATHEXT是windows下的文件擴展名環境變量 后面的語法是從PATHEXT中刪除.JS 然后執行 node ... ... webpack.js 命令,
去除掉擴展名的作用是為了防止執行到node.js文件
比如當前文件夾下有一個node.js文件, 如果直接執行node命令可能會默認用vscode打開這個.js文件
// vue-cli-service文件內容
// unix系的shell腳本
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
esac
if [ -x "$basedir/node" ]; then
"$basedir/node" "$basedir/../_@vue_cli-service@3.12.1@@vue/cli-service/bin/vue-cli-service.js" "$@"
ret=$?
else
node "$basedir/../_@vue_cli-service@3.12.1@@vue/cli-service/bin/vue-cli-service.js" "$@"
ret=$?
fi
exit $ret
