Electron无法下载问题
Electron打包,我把npm
切换成yarn
时,导致electron二进制包
下载不了。
问题1:
执行:yarn install
报错,electron二进制文件下载不了。因为被墙了
我使用的yarn是4.0版本。正常通过npm命令安装的是1.0版本
原因
之前一直使用 yarn1
版本,但发现低版本对 TS
语言支持的不是很好,编译的时候会报错误信息。查了资料以后说是要升级到 yarn3
版本以上 TS
就不会报错了。目前最新的是4.0版本,升到最新以后发现之前的 Electron
配置文件 config
不能使用了
ini
ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/
ELECTRON_BUILDER_BINARIES_MIRROR=https://npmmirror.com/mirrors/electron-builder-binaries/
导致上面的环境变量配置不上去,一直下载 electron
时报错。
解决方案
在工程根目录下创建 shell
脚本,yarn_install.sh
文件:
bash
#!/bin/bash
rm -rf node_modules && rm -rf yarn.lock && rm -rf dist
export ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
export ELECTRON_BUILDER_BINARIES_MIRROR="https://npmmirror.com/mirrors/electron-builder-binaries/"
yarn cache clean --all && yarn install
通过命令行上下文中指定ELECTRON_MIRROR和ELECTRON_BUILDER_BINARIES_MIRROR变量。可以让命令:
yarn install
正常执行
问题2
当我使用 electron-builder
工具打包 windows/macos/linux
平时的包时报错:
bash
• electron-builder version=24.13.3 os=22.6.0
• loaded configuration file=/Users/yuhang/yuyue/project/webstorm/electron-vite-template/build.json
• writing effective config file=build/builder-effective-config.yaml
• packaging platform=darwin arch=arm64 electron=29.1.2 appOutDir=build/mac-arm64
⨯ Get "https://github.com/electron/electron/releases/download/v29.1.2/electron-v29.1.2-darwin-arm64.zip": Method Not Allowed
github.com/develar/app-builder/pkg/download.(*Downloader).follow.func1
/Volumes/data/Documents/app-builder/pkg/download/downloader.go:206
github.com/develar/app-builder/pkg/download.(*Downloader).follow
/Volumes/data/Documents/app-builder/pkg/download/downloader.go:234
github.com/develar/app-builder/pkg/download.(*Downloader).DownloadNoRetry
/Volumes/data/Documents/app-builder/pkg/download/downloader.go:128
github.com/develar/app-builder/pkg/download.(*Downloader).Download
/Volumes/data/Documents/app-builder/pkg/download/downloader.go:112
github.com/develar/app-builder/pkg/electron.(*ElectronDownloader).doDownload
/Volumes/data/Documents/app-builder/pkg/electron/electronDownloader.go:192
github.com/develar/app-builder/pkg/electron.(*ElectronDownloader).Download
/Volumes/data/Documents/app-builder/pkg/electron/electronDownloader.go:177
github.com/develar/app-builder/pkg/electron.downloadElectron.func1.1
/Volumes/data/Documents/app-builder/pkg/electron/electronDownloader.go:73
github.com/develar/app-builder/pkg/util.MapAsyncConcurrency.func2
/Volumes/data/Documents/app-builder/pkg/util/async.go:68
runtime.goexit
/usr/local/Cellar/go/1.17/libexec/src/runtime/asm_arm64.s:1133
⨯ /Users/yuhang/yuyue/project/webstorm/electron-vite-template/node_modules/app-builder-bin/mac/app-builder_arm64 process failed ERR_ELECTRON_BUILDER_CANNOT_EXECUTE
Exit code:
1 failedTask=build stackTrace=Error: /Users/yuhang/yuyue/project/webstorm/electron-vite-template/node_modules/app-builder-bin/mac/app-builder_arm64 process failed ERR_ELECTRON_BUILDER_CANNOT_EXECUTE
Exit code:
1
at ChildProcess.<anonymous> (/Users/yuhang/yuyue/project/webstorm/electron-vite-template/node_modules/builder-util/src/util.ts:252:14)
at Object.onceWrapper (node:events:629:26)
at ChildProcess.emit (node:events:514:28)
at maybeClose (node:internal/child_process:1105:16)
at Process.ChildProcess._handle.onexit (node:internal/child_process:305:5)
Process finished with exit code 1
这个错误提示,electron二进制文件下载不了
原因
我查看了 electron下载部分的源代码有问题,需要改 node_modules
的代码。这种方式好像不太好
我查了很多资料 npm
好像可以配置文件里加参数解决。但 yarn
4.0版本,没什么资料。官方文档上查了以后发现,也不能配置 ELECTRON_MIRROR
这些变量。
我查了electron的官网信息,说是会把这些缓存文件放在下面的路径:
- Linux:
$XDG_CACHE_HOME
or~/.cache/electron/
- macOS:
~/Library/Caches/electron/
- Windows:
$LOCALAPPDATA/electron/Cache
or~/AppData/Local/electron/Cache/
没有完美解决方案,目前我的方式是自己去下载对应的 electron
版本到缓存路径中。这样打包的时候,直接读缓存不用去下载了。
解决方案
我自己用golang
写了脚本。轻量的脚手架,自动读取 package.json
文件中的 electron
版本号。去第三方镜像网站自动下载。写到不同平台的缓存路径下。使用 golang
是因为可以跨平台,所以系统都可以直接使用。
electron-download.go
脚本代码:
go
package main
import (
"encoding/json"
"errors"
"fmt"
"github.com/cheggaaa/pb/v3"
"io"
"log"
"net/http"
"os"
"os/user"
"path"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"time"
)
func main() {
arch := [3]string{"x64", "i32", "arm64"}
baseURL := "https://npmmirror.com/mirrors/electron/"
var version, _ = readPackageFile()
// 生成需要下载的electron二进制包
var downloadUrls []string
for _, s := range arch {
url, err := buildDownloadURL(baseURL, version, s)
if err == nil {
downloadUrls = append(downloadUrls, url)
}
}
downloadElectron(downloadUrls)
}
// 获取缓存目录
func getCacheDir() string {
usr, _ := user.Current()
platform := runtime.GOOS
var cacheDir string
if platform == "linux" {
cacheDir = filepath.Join(usr.HomeDir, ".cache", "electron")
} else if platform == "darwin" {
cacheDir = filepath.Join(usr.HomeDir, "Library", "Caches", "electron")
} else if platform == "windows" {
cacheDir = filepath.Join(usr.HomeDir, "AppData", "Local", "electron", "Cache")
}
return cacheDir
}
// 生成下载地址
func buildDownloadURL(baseURL string, version string, arch string) (string, error) {
platform := runtime.GOOS
filename := ""
if platform != "windows" && arch == "i32" {
return "", errors.New("")
} else {
filename = fmt.Sprintf("electron-v%s-%s-%s.zip", version, platform, arch)
}
url := baseURL + version + "/" + filename
return url, nil
}
// 下载Electron
func downloadElectron(downloadUrls []string) {
cacheDir := getCacheDir()
for _, url := range downloadUrls {
// 使用 path 包获取文件名
filename := path.Base(url)
// 如果 URL 中包含查询参数,需要额外处理
if strings.ContainsRune(filename, '?') {
filename = strings.Split(filename, "?")[0]
}
savePath := filepath.Join(cacheDir, filename)
file := downloadFile(url, savePath)
if file {
fmt.Printf("下载完成,保存至: %s\n", savePath)
}
}
}
// 下载文件
func downloadFile(url string, savePath string) bool {
// 检查本地文件是否已存在
if _, err := os.Stat(savePath); err == nil {
fmt.Printf("\n文件已存在,无需下载:%s\n本地文件路径:%s \n\n", url, savePath)
return false
}
client := http.DefaultClient
client.Timeout = 60 * 10 * time.Second
reps, err := client.Get(url)
if err != nil {
log.Panic(err.Error())
}
if reps.StatusCode == http.StatusOK {
//保存文件
file, err := os.Create(savePath)
if err != nil {
log.Panic(err.Error())
}
defer file.Close() //关闭文件
//获取下载文件的大小
length := reps.Header.Get("Content-Length")
size, _ := strconv.ParseInt(length, 10, 64)
body := reps.Body //获取文件内容
bar := pb.Full.Start64(size)
bar.SetWidth(120) //设置进度条宽度
bar.SetRefreshRate(10 * time.Millisecond) //设置刷新速率
defer bar.Finish()
// create proxy reader
barReader := bar.NewProxyReader(body)
//写入文件
writer := io.Writer(file)
io.Copy(writer, barReader)
//defer fmt.Printf("\n下载完成,保存至: %s\n", savePath)
}
return true
}
// 读取当前目录下的文件
func readPackageFile() (string, error) {
// 读取 package.json 文件
filePath := "package.json"
jsonData, err := os.ReadFile(filePath)
if err != nil {
panic(err)
}
var parsedData map[string]interface{}
err = json.Unmarshal(jsonData, &parsedData)
if err != nil {
return "", err
}
electronVersion := parsedData["devDependencies"].(map[string]interface{})["electron"].(string)
re := regexp.MustCompile(`\d+.\d+.\d+`)
versionNumbers := re.FindString(electronVersion)
return versionNumbers, nil
}
可以去我的 github
上下载对应的执行文件放到 package.json
同级目录就可以了。
进入到项目根目录,执行命令:
arduino
yarn install && ./electron-download-mac-arm64 // mac m1版本
yarn install && ./electron-download-mac-amd64 // mac x86版本
yarn install && ./electron-download-linux-amd64 // linux x86版本
yarn install && ./electron-download-linux-arm64 // linux x86版本
yarn install && ./electron-download-linux-arm64 // windows x86版本
yarn install && ./electron-download-windows-amd64.exe // mac x86版本
yarn install && ./electron-download-windows-arm64.exe // mac x86版本
当前环境已经安装好了
- mac执行打包脚本:
ini
export ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
export ELECTRON_BUILDER_BINARIES_MIRROR="https://npmmirror.com/mirrors/electron-builder-binaries/"
yarn run build:mac
- windows32位打包:
ini
export ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
export ELECTRON_BUILDER_BINARIES_MIRROR="https://npmmirror.com/mirrors/electron-builder-binaries/"
yarn run build:win32
- windows64位打包:
ini
export ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
export ELECTRON_BUILDER_BINARIES_MIRROR="https://npmmirror.com/mirrors/electron-builder-binaries/"
yarn run build:win64
都需要配置环境变量