Electron无法下载问题(yarn 4.0版本)

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
​

都需要配置环境变量

相关推荐
慧一居士21 分钟前
flex 布局完整功能介绍和示例演示
前端
DoraBigHead23 分钟前
小哆啦解题记——两数失踪事件
前端·算法·面试
一斤代码6 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
中微子6 小时前
React Router 源码深度剖析解决面试中的深层次问题
前端·react.js
光影少年6 小时前
从前端转go开发的学习路线
前端·学习·golang
中微子6 小时前
React Router 面试指南:从基础到实战
前端·react.js·前端框架
3Katrina6 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
前端_学习之路7 小时前
React--Fiber 架构
前端·react.js·架构
伍哥的传说8 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js
qq_424409198 小时前
uniapp的app项目,某个页面长时间无操作,返回首页
前端·vue.js·uni-app