likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 8

Electron无法下载问题

Electron打包,我把npm切换成yarn时,导致electron二进制包下载不了。

问题1:

执行:yarn install 报错,electron二进制文件下载不了。因为被墙了

我使用的yarn是4.0版本。正常通过npm命令安装的是1.0版本

原因

之前一直使用 yarn1 版本,但发现低版本对 TS 语言支持的不是很好,编译的时候会报错误信息。查了资料以后说是要升级到 yarn3 版本以上 TS 就不会报错了。目前最新的是4.0版本,升到最新以后发现之前的 Electron 配置文件 config 不能使用了

ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/
ELECTRON_BUILDER_BINARIES_MIRROR=https://npmmirror.com/mirrors/electron-builder-binaries/

导致上面的环境变量配置不上去,一直下载 electron 时报错。

解决方案

在工程根目录下创建 shell脚本,yarn_install.sh 文件:

#!/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 平时的包时报错:

  • 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 是因为可以跨平台,所以系统都可以直接使用。

github地址https://github.com/yuhanghate/electron-download.git

electron-download.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 同级目录就可以了。

进入到项目根目录,执行命令:

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执行打包脚本:
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位打包:
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位打包:
export ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
export ELECTRON_BUILDER_BINARIES_MIRROR="https://npmmirror.com/mirrors/electron-builder-binaries/"
yarn run build:win64

都需要配置环境变量