解決Electron安裝報(bào)錯(cuò)問題

Electron是一個(gè)優(yōu)秀的跨平臺(tái)桌面端應(yīng)用的框架,官網(wǎng)給出的簡紹很簡單:使用 JavaScript, HTML 和 CSS 構(gòu)建跨平臺(tái)的桌面應(yīng)用。好多朋友也想試試使用前端技術(shù)來做一個(gè)桌面應(yīng)用,但是往往在安裝的時(shí)候就直接報(bào)錯(cuò)了,大多數(shù)的錯(cuò)誤是:

Error: read ECONNRESET
# 或者
Error: Electron failed to install correctly ...

解決辦法

解決辦法也是簡單的,如果你是安裝失敗了,那么先把node_modules中的electron刪掉,然后重新開始下面的步驟。

  1. 設(shè)置淘寶鏡像源(推薦使用nrm,這一步是為了保證其他依賴不報(bào)錯(cuò))
npm install -g nrm
nrm use taobao
  1. 設(shè)置環(huán)境變量并安裝
# Mac系統(tǒng) 
ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron/ 
npm install 
# Windows系統(tǒng) 
# 全局依賴cross-env為了把參數(shù)寫入環(huán)境變量 當(dāng)然直接修改環(huán)境變量也可以 
npm install -g cross-env 
cross-env ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron 
npm install 

然后稍等片刻就可以了。

深入研究

通過上面的設(shè)置基本上就解決了Electron安裝的問題,現(xiàn)在我們可以深入一下,看看它是怎么解決的。首先我們進(jìn)入它的源代碼,這個(gè)里面有一個(gè)npm的文件夾,這個(gè)路徑下存放的就是npm上的Electron依賴。打開看看你會(huì)發(fā)現(xiàn)只有幾個(gè)文件,沒錯(cuò)Electron的依賴包就這么點(diǎn)東西。

那么這么點(diǎn)東西怎么做跨平臺(tái)的應(yīng)用的呢?首先看一下package.json文件,為了方便查看,我拷貝過來一份,如下:

{
  "main": "index.js",
  "types": "electron.d.ts",
  "bin": {
    "electron": "cli.js"
  },
  "scripts": {
    "postinstall": "node install.js"
  },
  "dependencies": {
    "@electron/get": "^1.0.1",
    "@types/node": "^12.0.12",
    "extract-zip": "^1.0.3"
  },
  "engines": {
    "node": ">= 8.6"
  }
}

內(nèi)容很少,但有2個(gè)部分很重要。一個(gè)是script,可以看到里面有一個(gè)postinstall的鉤子命令,這條命令會(huì)在下載完依賴以后執(zhí)行一下,也就說當(dāng)依賴安裝完后會(huì)執(zhí)行node install.js。另外一個(gè)重要的部分就是bin,它指定了運(yùn)行全局依賴時(shí)的入口文件,也就是cli.js文件,我們稍后再說這個(gè)。

先簡單的看一下install.js,里面最主要的部分是調(diào)用了方法downloadArtifact,用來下載跟平臺(tái)相關(guān)的Electron可執(zhí)行文件。下載完后調(diào)用extractFile方法,把文件解壓了,最后在path.txt中把執(zhí)行文件的路徑寫進(jìn)去,這個(gè)路徑下是不同平臺(tái)下的可執(zhí)行文件的路徑。

最后我們看一下他是從哪里下載的。首先downloadArtifact方法是在@electron/get依賴?yán)锩?。我們進(jìn)入到src/index中。

此時(shí)我們可以看到url是通過getArtifactRemoteURL方法獲取的,然后我們看一下getArtifactRemoteURL方法,源碼在這里。

getArtifactRemoteURL方法中,可以看到,基礎(chǔ)路徑base是通過mirrorVar函數(shù)返回的,默認(rèn)情況是沒有nightly的,所以默認(rèn)情況下是下面這個(gè)樣子的:

process.env[`NPM_CONFIG_ELECTRON_MIRROR`] ||
process.env[`npm_config_electron_MIRROR`] ||
process.env[`npm_package_config_electron_mirror`] ||
process.env[`ELECTRON_MIRROR`] ||
options['mirror'] ||
defaultValue

而我們很少傳入env的,options也沒有mirror,所以通常是defaultValue,具體值如下:

綜上,我們可以看到默認(rèn)情況下安裝的時(shí)候會(huì)在github的release處下載一個(gè)平臺(tái)相關(guān)的可執(zhí)行文件。但是往往在國內(nèi)github會(huì)很慢,所以這就導(dǎo)致了下載失敗的問題,如果我們的env中傳入ELECTRON_MIRROR,那就會(huì)走該值所對(duì)應(yīng)的地址,通常我們使用淘寶的鏡像http://npm.taobao.org/mirrors/electron。

同樣的,在構(gòu)建Windows系統(tǒng)的時(shí)候可能會(huì)用到依賴windows-build-tools,該依賴會(huì)安裝一個(gè)Python,這時(shí)可以使用淘寶的鏡像文件會(huì)更快一些:

# Macos
"PYTHON_MIRROR=http://npm.taobao.org/mirrors/python" npm install --global --production windows-build-tools
# Windows
# 若全局已經(jīng)安裝過cross-env那么就不需要再安裝了
npm install -g cross-env
cross-env PYTHON_MIRROR=http://npm.taobao.org/mirrors/python npm install --global --production windows-build-tools

淘寶更多的開源軟件的鏡像可以參考這里

啟動(dòng)過程

下載過程基本上我們已經(jīng)明白了,現(xiàn)在說一下啟動(dòng)過程。一般啟動(dòng)Electron的時(shí)候調(diào)用的命令是electron .,而electron命令其實(shí)是調(diào)用依賴包中的cli.js文件,該文件內(nèi)容如下:

#!/usr/bin/env node

var electron = require('./')

var proc = require('child_process')

var child = proc.spawn(electron, process.argv.slice(2), { stdio: 'inherit', windowsHide: false })
child.on('close', function (code) {
  process.exit(code)
})

const handleTerminationSignal = function (signal) {
  process.on(signal, function signalHandler () {
    if (!child.killed) {
      child.kill(signal)
    }
  })
}

handleTerminationSignal('SIGINT')
handleTerminationSignal('SIGTERM')

其中var electron = require('./')的時(shí)候是引入當(dāng)前文件夾下的index.js文件,內(nèi)容如下:

var fs = require('fs')
var path = require('path')

var pathFile = path.join(__dirname, 'path.txt')

function getElectronPath () {
  if (fs.existsSync(pathFile)) {
    var executablePath = fs.readFileSync(pathFile, 'utf-8')
    if (process.env.ELECTRON_OVERRIDE_DIST_PATH) {
      return path.join(process.env.ELECTRON_OVERRIDE_DIST_PATH, executablePath)
    }
    return path.join(__dirname, 'dist', executablePath)
  } else {
    throw new Error('Electron failed to install correctly, please delete node_modules/electron and try installing again')
  }
}

module.exports = getElectronPath()

index.js文件內(nèi)容很少,主要是返回了一個(gè)字符串的地址,也就是當(dāng)前路徑下的dist文件夾下的可執(zhí)行文件的路徑。還記得下載完后往path.txt里面寫了一個(gè)可執(zhí)行文件的路徑嗎?

我們再回到cli.js文件中,從代碼中可以看出,里面啟動(dòng)了一個(gè)子進(jìn)程,用子進(jìn)程啟動(dòng)Electron的可執(zhí)行文件,并且把參數(shù)傳進(jìn)去了。最后如果主進(jìn)程中斷或者出現(xiàn)錯(cuò)誤,那么就把子進(jìn)程殺掉。當(dāng)然你也可以直接雙擊dist下的可執(zhí)行文件,它會(huì)啟動(dòng)一個(gè)默認(rèn)的頁面。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容