解決Electron安裝報錯問題


鏈接:https://www.kai666666.top/2019/11/06/%E8%A7%A3%E5%86%B3electron%E5%AE%89%E8%A3%85%E6%8A%A5%E9%94%99%E9%97%AE%E9%A2%98/#more

Electron是一個優秀的跨平台桌面端應用的框架,官網給出的簡紹很簡單:使用 JavaScript, HTML 和 CSS 構建跨平台的桌面應用。好多朋友也想試試使用前端技術來做一個桌面應用,但是往往在安裝的時候就直接報錯了,大多數的錯誤是:

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

解決辦法

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

  1. 設置淘寶鏡像源(推薦使用nrm,這一步是為了保證其他依賴不報錯)

    1
    2
    npm install -g nrm
    nrm use taobao
  2. 設置環境變量並安裝

    1
    2
    3
    4
    5
    # Mac系統
    ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron/ npm install

    # Windows系統
    set "ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron" && npm install

    然后稍等片刻就可以了。

深入研究

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

Electron依賴中的內容

那么這么點東西怎么做跨平台的應用的呢?首先看一下package.json文件,為了方便查看,我拷貝過來一份,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"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"
}
}

內容很少,但有2個部分很重要。一個是script,可以看到里面有一個postinstall的鈎子命令,這條命令會在下載完依賴以后執行一下,也就說當依賴安裝完后會執行node install.js。另外一個重要的部分就是bin,它指定了運行全局依賴時的入口文件,也就是cli.js文件,我們稍后再說這個。

先簡單的看一下install.js,里面最主要的部分是調用了方法downloadArtifact,用來下載跟平台相關的Electron可執行文件。下載完后調用extractFile方法,把文件解壓了,最后在path.txt中把執行文件的路徑寫進去,這個路徑下是不同平台下的可執行文件的路徑。

install.js

最后我們看一下他是從哪里下載的。首先downloadArtifact方法是在@electron/get依賴里面。我們進入到src/index中。

downloadArtifact方法

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

getArtifactRemoteURL方法

getArtifactRemoteURL方法中,可以看到,基礎路徑base是通過mirrorVar函數返回的,默認情況是沒有nightly的,所以默認情況下是下面這個樣子的:

1
2
3
4
5
6
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,具體值如下:

defaultValue

綜上,我們可以看到默認情況下安裝的時候會在github的release處下載一個平台相關的可執行文件。但是往往在國內github會很慢,所以這就導致了下載失敗的問題,如果我們的env中傳入ELECTRON_MIRROR,那就會走該值所對應的地址,通常我們使用淘寶的鏡像http://npm.taobao.org/mirrors/electron

同樣的,在構建Windows系統的時候可能會用到依賴windows-build-tools,該依賴會安裝一個Python,這時可以使用淘寶的鏡像文件會更快一些:

1
2
3
4
# Macos
"PYTHON_MIRROR=http://npm.taobao.org/mirrors/python" npm install --global --production windows-build-tools
# Windows
set "PYTHON_MIRROR=http://npm.taobao.org/mirrors/python" && npm install --global --production windows-build-tools

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

啟動過程

下載過程基本上我們已經明白了,現在說一下啟動過程。一般啟動Electron的時候調用的命令是electron .,而electron命令其實是調用依賴包中的cli.js文件,該文件內容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/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('./')的時候是引入當前文件夾下的index.js文件,內容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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文件內容很少,主要是返回了一個字符串的地址,也就是當前路徑下的dist文件夾下的可執行文件的路徑。還記得下載完后往path.txt里面寫了一個可執行文件的路徑嗎?

我們再回到cli.js文件中,從代碼中可以看出,里面啟動了一個子進程,用子進程啟動Electron的可執行文件,並且把參數傳進去了。最后如果主進程中斷或者出現錯誤,那么就把子進程殺掉。當然你也可以直接雙擊dist下的可執行文件,它會啟動一個默認的頁面。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM