記錄macOS下由yarn與npm差異引發(fā)的Electron鏡像地址讀取問題
寫在前面:該問題僅僅出現(xiàn)在Linux和macOS上,Windows上不存在該問題!
初始背景
最近筆者重新拾起了Electron,把最新版Electron的官方文檔閱讀了一遍。眾所周知,Electron作為依賴在安裝的時(shí)候,其二進(jìn)制文件下載在國內(nèi)一直以來都是問題(因?yàn)槟J(rèn)會(huì)從github上下載),好在現(xiàn)在Electron的官方文檔已經(jīng)寫的非常詳細(xì)了:安裝指導(dǎo) | Electron (electronjs.org),只需要配置一個(gè)鏡像地址到.npmrc
中:
ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
記住這個(gè)大寫的Key
筆者由于是新的機(jī)器,還沒有配置改值,所以找到.npmrc
文件的配置了上述的鏡像后,便開開心心的準(zhǔn)備進(jìn)行項(xiàng)目搭建了。
問題出現(xiàn)
然而,當(dāng)筆者準(zhǔn)備使用yarn執(zhí)行如下命令的時(shí)候,卻出了問題:
yarn add -D electron
運(yùn)行啟動(dòng)以后,在Electron安裝的環(huán)境一直卡住了很久很久。
咦,難道鏡像配置寫錯(cuò)了嗎?仔細(xì)對(duì)比以后,沒有問題。難道因?yàn)槲业木W(wǎng)絡(luò)訪問很慢嗎?等到訪問超時(shí)以后,發(fā)現(xiàn)一個(gè)IP地址超時(shí)了,心想國內(nèi)鏡像再怎么也不應(yīng)該超時(shí),盲猜鏡像地址沒有生效。于是乎,準(zhǔn)備嘗試對(duì)下載Electron二進(jìn)制文件的過程進(jìn)行debug。
問題排查
首先定位到node_module/electron
包,能夠看到有一段安裝后腳本執(zhí)行命令(postinstall
):
關(guān)于postinstall的詳細(xì)說明:scripts | npm Docs (npmjs.com)
也就是說,node_module/electron
本身npm包install完成以后,還會(huì)執(zhí)行其包內(nèi)的install.js。
定位進(jìn)入了node_module/electron
包下的install.js
,該腳本內(nèi)部主要邏輯是先檢查Electron的二進(jìn)制緩存,如果不存在緩存,則使用來自@electron/get
包中提供的downloadArtifact
方法從遠(yuǎn)端下載Electron二進(jìn)制制品文件。
我們暫時(shí)先不看緩存讀寫的邏輯,著重了解遠(yuǎn)端下載的邏輯,所以我們進(jìn)入@electron/get
包中的downloadArtifact
:
查看@electron/get
包下的index.js內(nèi)容:
前面我們提到,懷疑鏡像地址沒有生效導(dǎo)致下載超時(shí),所以我們重點(diǎn)關(guān)注一下這里通過getArtifactRemoteURL
方法得到的url
值,
由于每一次這個(gè)包都會(huì)重新安裝,我們不太好調(diào)試這個(gè)值,所以,我們做一個(gè)簡(jiǎn)單的trick:
- 找到這個(gè)包的緩存(macOS上的路徑為:
~/Library/Caches/Yarn/v6/npm-@electron-get-xxxx
):
- 找到上述indexjs代碼,并添加一段日志打印:
- 準(zhǔn)備完畢以后,我們重新在demo項(xiàng)目下執(zhí)行
yarn add -D electron
。執(zhí)行以后,等到超時(shí)以后,發(fā)現(xiàn)控制臺(tái)日志打印如下:
Why?。繛槭裁催@個(gè)下載的Electron二進(jìn)制文件地址依然是github的?于是,我們有必要進(jìn)一步查看這個(gè)URL是如何得到。
繼續(xù)查看代碼,這個(gè)url
來源于artifact-utils
中的getArtifactRemoteURL
方法,而這個(gè)方法里面關(guān)于最終返回的url
最重要的部分是下圖所示的base
的值:
而這個(gè)base
值來源于mirrorVar
這個(gè)方法:
根據(jù)上面代碼的邏輯,name值為"mirror"
,options未使用,defaultValue為:
"https://github.com/electron/electron/releases/download/"
也就是說,在后面的邏輯中,如果沒有從process.env
中找到對(duì)應(yīng)的值,那么就會(huì)使用默認(rèn)的github官方制品地址的值。按照代碼邏輯,運(yùn)行到這個(gè)方法的時(shí)候,會(huì)從process.env
中嘗試獲?。?/p>
- "NPM_CONFIG_ELECTRON_MIRROR"
- "npm_config_electron_mirror"
- "npm_package_config_electron_mirror"
- "ELECTRON_MIRROR"
環(huán)境變量—— 配置 | npm 中文網(wǎng) (nodejs.cn)
任何以
npm_config_
開頭的環(huán)境變量都將被解釋為配置參數(shù)。 例如,將npm_config_foo=bar
放入您的環(huán)境中會(huì)將foo
配置參數(shù)設(shè)置為bar
。 任何未賦值的環(huán)境配置都將被賦值為true
。 配置值不區(qū)分大小寫,因此NPM_CONFIG_FOO=bar
的工作方式相同。 但是,請(qǐng)注意,在scripts
內(nèi)部,npm 將設(shè)置自己的環(huán)境變量,并且 Node 會(huì)更喜歡那些小寫版本,而不是您可能設(shè)置的任何大寫版本。 詳情見此問題。請(qǐng)注意,您需要使用下劃線而不是破折號(hào),因此
--allow-same-version
將變?yōu)?npm_config_allow_same_version=true
。此外,如果是配置在npmrc里面的配置,也會(huì)在npm/yarn啟動(dòng)的時(shí)候被作為環(huán)境變量放到process.env中被訪問。
那我們?cè)?code>.npmrc中配置的ELECTRON_MIRROR
,在process.env
中變成了什么呢?通過添加日志打印,我們會(huì)看到:
可以看到,在process.env
中,這個(gè)鍵為"npm_config_ELECTRON_MIRROR"
(npm_config
小寫,ELECTORN_MIRROR
大寫)。我們知道,nodejs中object對(duì)象的屬性值是大小寫敏感的!所以,當(dāng)上面的mirrorVar
代碼運(yùn)行,嘗試獲取process.env
中的值的時(shí)候,根本找不到了,因?yàn)闆]有"NPM_CONFIG_ELECTRON_MIRROR"
、"npm_config_electron_mirror"
、"npm_package_config_electron_mirror"
、"ELECTRON_MIRROR"
這些屬性。
然而,如果我們使用npm進(jìn)行安裝的時(shí)候:
npm install -D electron
又能夠很快安裝。Why?!難道npm和yarn下的運(yùn)行環(huán)境有差異嗎?為了驗(yàn)證,我們編寫一個(gè)簡(jiǎn)單的index.js代碼:
console.log("process.env['npm_config_electron_mirror']", process.env['npm_config_electron_mirror']);
console.log("process.env['NPM_CONFIG_ELECTRON_MIRROR']", process.env['NPM_CONFIG_ELECTRON_MIRROR']);
console.log("process.env['npm_config_ELECTRON_MIRROR']", process.env['npm_config_ELECTRON_MIRROR']);
然后,在package.json中添加腳本:
{
"name": "simple-electron-main-app",
"version": "1.0.0",
"scripts": {
+ "start": "node index.js"
},
"devDependencies": {}
}
最后,我們分別使用yarn(yarn start
)和npm(npm run start
)來運(yùn)行腳本:
在yarn運(yùn)行上下文中,.npmrc
中的"ELECTRON_MIRROR"
直接拼接到了"npm_config_"
后邊,作為process.env
的一個(gè)屬性,所以你只能訪問process.env["npm_config_ELECTRON_MIRROR"]
得到值;
在npm運(yùn)行山下文中,.npmrc
中的"ELECTRON_MIRROR"
首先被轉(zhuǎn)為了小寫,然后拼接到了"npm_config_"
后邊,作為了process.env
的屬性,所以你需要訪問process.env["npm_config_electron_mirror"]
來得到值。
macOS解決方式
終于,我們能解釋為什么當(dāng)我們?cè)?code>.npmrc配置大寫的ELECTRON_MIRROR
的時(shí)候,使用yarn add -D electron
安裝electron的時(shí)候,二進(jìn)制鏡像地址沒有生效了。那么,解決的辦法也非常簡(jiǎn)單,兩種:
-
.npmrc
配置改為小寫key:electron_mirror="https://npmmirror.com/mirrors/electron/"
; - 使用
npm
上下文環(huán)境進(jìn)行安裝。
個(gè)人更加建議按照第一種方式配置,不然大小寫敏感的坑太容易發(fā)生了。
關(guān)于Windows的特別說明
process.env | Node.js API 文檔 (nodejs.cn)
在 Windows 操作系統(tǒng)上,環(huán)境變量不區(qū)分大小寫。
const { env } = require('node:process');
env.TEST = 1;
console.log(env.test);
// => 1
也就是說,在Windows機(jī)器上,即使process.env
中的key為"npm_config_ELECTRON_MIRROR"
,你也可以通過"npm_config_electron_mirror"
或者是"NPM_CONFIG_ELECTRON_MIRROR"
來訪問這個(gè)值:
文章來源:http://www.zghlxwxcb.cn/news/detail-456105.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-456105.html
到了這里,關(guān)于macOS下由yarn與npm差異引發(fā)的Electron鏡像地址讀取問題的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!