這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
npm 是 node 捆綁的依賴管理器,常用程度可想而知,那么你每天都在 npm/yarn run 的命令到底是如何運行專案的呢?
前端專案中運行 npm run xxx 的時候發生了什么?
大家都知道目前的 node 是捆綁 npm 的,npm 是 node 的依賴管理器,雖然它不是唯一的選擇,我們還有 pnpm/yarn/cnpm/ni ,
但是,的依賴管理器都是在解決 npm 的某個痛點,對于 npm 依賴宣告檔案 ?
package.json?
本身是基本沒有變化的,
例如我們可以使用 ?
npm run serve?
運行某個命令, 也可以使用 ?
yarn serve?
? 運行某個命令,
可以看到在這個地方 yarn 可以省略 run 這個引數,
但是,他們都只是對 ?
?package.json?
進行決議而已,例如下面的檔案,當運行 ?
npm run serve?
時,其實就是運行該 json 檔案中的 ?
scripts?
下的 ?
?serve?
鍵對應的命令,
{
"name": "h5",
"version": "1.0.7",
"private": true,
"scripts": {
"serve": "vue-cli-service serve"
},
"dependencies": {
"axios": "^0.19.2",
"vuex": "^3.4.0"
},
"devDependencies": {
"node-sass": "^4.12.0"
}
}
上面說是 ??命令?
? 只是用于方便理解,例如:
npm run server # 類似于在命令列運行以下命令 vue-cli-service serve
通過 npm run 與直接運行命令的區別
還是用上面的配置來描述:
{
"scripts": {
"serve": "vue-cli-service serve"
}
}
npm 在運行 ?
vue-cli-service serve?
這條命令的時候,會先在當前 ?
node_modules/.bin?
下面看有沒有同名的可執行檔案,如果有,則使用其運行,
這里我們可以打開這個目錄看看:

如果直接在命令列中運行 ?
?vue-cli-service serve?
這條命令,是不會從 node_modules 中查找可執行程式的,
運行可執行檔案
那么什么叫可執行檔案呢?上面的圖中有很多個同名的 vue-cli-service ,到底是運行哪個?
我們先來分析這幾個檔案怎么來的?
例如 ?
@vue/cli-service?
有以下 ?
package.json?
檔案,注意 bin 欄位,當我們運行 ?
?npm i @vue/cli-service?
這條命令時,npm 就會在 ?
?node_modules/.bin/?
目錄中創建好以 ?
?vue-cli-service?
為名的幾個可執行檔案了,
{
"name": "@vue/cli-service",
"version": "4.4.6",
"description": "local service for vue-cli projects",
"main": "lib/Service.js",
"typings": "types/index.d.ts",
"bin": {
"vue-cli-service": "bin/vue-cli-service.js"
}
}
對于可執行?這個定義,每個系統不一樣,在 windows 系統上,可執行檔案是通過組策略和環境變數決定的,
使用 ?
set pathext?
可以查看 ?
pathext?
這個環境變數,他定義了可以作為可執行檔案的后綴,
# 查看可執行檔案后綴 set pathext

由上面的配置可以發現,我們常見的 exe 也在其中,這個可執行檔案在 windows 上,在命令列中輸入檔案名或雙擊時即可以運行,
在 unix 系統上面,是通過設定檔案的屬性為可執行,再在檔案中的第一行宣告解釋器來運行的,

如果我們在 cmd 里運行的時候,windows 一般是呼叫了 ?
?vue-cli-service.cmd
這個檔案,這是 windows 下的批處理腳本:
@ECHO off SETLOCAL CALL :find_dp0 SET _maybeQuote=" IF EXIST "%dp0%\node.exe" ( SET "_prog=%dp0%\node.exe" ) ELSE ( SET _maybeQuote= SET "_prog=node" SET PATHEXT=%PATHEXT:;.JS;=;% ) %_maybeQuote%%_prog%%_maybeQuote% "%dp0%\..\_@[email protected]@@vue\cli-service\bin\vue-cli-service.js" %* ENDLOCAL EXIT /b %errorlevel% :find_dp0 SET dp0=%~dp0 EXIT /b
所以當我們運行 ?
?vue-cli-service serve?
這條命令的時候,就相當于運行 ?
?node_modules/.bin/vue-cli-service.cmd serve?
然后這個腳本會使用 node 去運行 ?
vue-cli-service.js?
這個 js 檔案,由于 node 中可以使用一系列系統相關的 api ,所以在這個 js 中可以做很多事情,例如讀取并分析運行這條命令的目錄下的檔案,根據模板生成檔案等,
# unix 系默認的可執行檔案,必須輸入完整檔案名 vue-cli-service # windows cmd 中默認的可執行檔案,當我們不添加后綴名時,自動根據 pathext 查找檔案 vue-cli-service.cmd # Windows PowerShell 中可執行檔案,可以跨平臺 vue-cli-service.ps1
這里多提了下,在 windows 中 cmd 腳本使用得比較多,兼容性也較好, powerShell 雖然比較強大,但他運行命令的方式由于和 cmd 命令有較大不同,這會導致你常常搞不清什么命令應該在什么解釋器里運行,
示例:運行命令的方式不兼容

示例:windows 很多系統會默認禁止此腳本運行,導致 npm 命令運行錯誤

所以如果遇到 powerShell 相關錯誤時建議用 cmd 試試,
注入相關運行時資訊
這一節我們通過除錯 npm 的原始碼來進行說明,
首先我們在 ? ?mockm?? 這個前端介面聯調工具的原始碼中先來個 debugger, 注意有從 process.env 中獲取 NPM_CONFIG_REGISTRY 這個環境變數,這是 npm 安裝時可配置的鏡像地址,

然后我們再看一下這個環境變數,在當前系統中是沒有定義的,

讓我們開始除錯 mockm package.json 中的 scripts ?
npm run s2?
{
"scripts": {
"s2": "node run.js remote --config=D:/git2/mockm/server/example/full.mm.config.js",
}
}

為了節省篇幅,這里直接斷點在關鍵地點:

這是 [email protected] 的原始碼,可以發現 npm 使用了 ? ?npm-lifecycle?? 這個依賴來運行的子行程呼叫我們的 ?
run.js?
檔案,
在通過 spawn 運行 run.js 的時候,同時設定了行程相關的一些資訊,這是由 node 原生支持的,

例如剛剛說到的 NPM_CONFIG_REGISTRY 環境變數,
下面把繼續進入下一個斷點, run.js 檔案:

可以發現子行程成功獲取了父行程給予的資訊,
總結
運行 npm run xxx
的時候,npm 會先在當前目錄的 node_modules/.bin 查找要執行的程式,如果找到則運行;
沒有找到則從全域的 node_modules/.bin 中查找,npm i -g xxx
就是安裝到到全域目錄;
如果全域目錄還是沒找到,那么就從 path 環境變數中查找有沒有其他同名的可執行程式,
本文轉載于:
https://blog.51cto.com/u_15077533/4531157
如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/544888.html
標籤:其他
上一篇:JavaScript 中的 apply、call、bind
下一篇:淺談JS原型

