Electron Forge 在 macOS M4 打包踩坑:Node.js 26 导致 make 异常中断

Electron Forge 在 macOS M4 打包踩坑:Node.js 26 导致 make 异常中断

最近在 macOS M4 上使用 Electron Forge 打包 Electron 44 项目时,遇到了一个比较隐蔽的问题。

最开始的表现是:

electron-forge make 一直停在打包阶段,看起来像是卡住了。

后来打开完整 Debug 才发现,它其实不是单纯"卡住",而是在 Electron 解压过程中提前结束,而且退出码还是 0

最后尝试切换 Node.js 版本后,打包恢复正常。

记录一下完整过程。

一、macOS DMG 打包配置

如果 Electron Forge 需要生成 macOS 的 .dmg 安装包,可以使用:

bash 复制代码
@electron-forge/maker-dmg

安装:

css 复制代码
npm install --save-dev @electron-forge/maker-dmg

然后在 Forge 配置中加入:

arduino 复制代码
{
  name: '@electron-forge/maker-dmg',
  platforms: ['darwin'],
  config: {},
}

如果只需要生成 DMG,也可以指定 maker:

css 复制代码
npx electron-forge make --targets=@electron-forge/maker-dmg

官方文档:

www.electronforge.io/config/make...


二、当前环境

当时的开发环境:

复制代码
macOS:Apple Silicon M4 / arm64
Electron:44.0.0
Electron Forge:7.11.2
Node.js:26.5.0
npm:11.17.0

确认 Node、npm 和 Forge 版本:

css 复制代码
node -v
npm -v
npx electron-forge --version

输出:

复制代码
v26.5.0
11.17.0
7.11.2

确认当前架构:

arduino 复制代码
node -p "process.arch + ' ' + process.platform"

输出:

复制代码
arm64 darwin

三、最开始的问题:electron-forge make 一直等待

直接执行:

go 复制代码
electron-forge make

前面的流程都正常:

sql 复制代码
✔ Checking your system
✔ Loading configuration
✔ Resolving make targets
✔ Preparing to package application
✔ Running generateAssets hook
✔ Running prePackage hook

然后进入:

java 复制代码
❯ Packaging application
❯ Packaging for arm64 on darwin
❯ Copying files
❯ Preparing native dependencies
❯ Finalizing package

最后一直停在:

go 复制代码
Finalizing package

从表面来看,很像 Electron Forge 在最终打包阶段卡死了。

而且没有任何 Error 信息,所以很难判断到底是:

  • Electron 下载问题
  • 原生依赖问题
  • Forge 配置问题
  • macOS 打包问题
  • Electron 本身的问题

四、第一次排查:打开 Electron Forge Debug

先尝试:

ini 复制代码
DEBUG=electron-forge:* electron-forge make

这时候能够看到 Forge 内部更多信息,例如:

csharp 复制代码
electron-forge:packager packaging with options {
  arch: 'arm64',
  platform: 'darwin',
  out: '/Users/user/IdeaProjects/my-app/out',
  electronVersion: '44.0.0'
}

可以确认当前目标是:

复制代码
darwin
arm64
Electron 44.0.0

但是日志依然停在:

go 复制代码
❯ Finalizing package

还不足以定位问题。


五、继续使用 DEBUG=* 查看完整日志

于是进一步执行:

ini 复制代码
DEBUG=* electron-forge make

这次可以看到:

  • electron-forge
  • electron-packager
  • @electron/get
  • extract-zip
  • sumchecker

等更底层的日志。

其中能够确认 Electron Packager 的运行环境:

perl 复制代码
Electron Packager 18.4.4
Node v26.5.0
Host Operating system: darwin 25.5.0 (arm64)

Electron 版本:

yaml 复制代码
Target Electron version: 44.0.0

目标平台:

yaml 复制代码
Target Platforms: darwin
Target Architectures: arm64

这时候已经可以确定,问题发生在 Electron Packager 的实际打包阶段。


六、排除 Electron 下载和缓存问题

日志中可以看到:

csharp 复制代码
electron-packager Downloading Electron with options {
  "platform":"darwin",
  "arch":"arm64",
  "version":"44.0.0",
  "artifactName":"electron"
}

紧接着:

kotlin 复制代码
@electron/get:index Cache hit

说明 Electron 44 的 macOS ARM64 安装包已经存在本地缓存。

继续往下还能看到 checksum 校验:

yaml 复制代码
Expected checksum:
076d79742986e1b100b69ebecc691cb07368045e54c9087cef631b8622b76a80

Actual:
076d79742986e1b100b69ebecc691cb07368045e54c9087cef631b8622b76a80

两个值完全一致。

因此当时基本排除了:

  • Electron 下载失败
  • GitHub 下载问题
  • Electron 缓存损坏
  • Electron ZIP 文件损坏
  • checksum 校验失败

Electron 安装包本身没有异常。


七、真正异常发生在 Electron 解压阶段

接下来日志进入:

python 复制代码
electron-packager Extracting electron-v44.0.0-darwin-arm64.zip

然后 extract-zip 开始正常解压:

python 复制代码
extract-zip zipfile entry Electron.app/
extract-zip extracting entry ...
extract-zip finished processing ...

包括各种 Electron 资源目录:

bash 复制代码
Electron.app/Contents/Resources/de.lproj/
Electron.app/Contents/Resources/ja.lproj/
Electron.app/Contents/Resources/zh_CN.lproj/

最后可以看到类似:

bash 复制代码
extract-zip zipfile entry Electron.app/Contents/Resources/electron.icns

以及:

bash 复制代码
extract-zip opening read stream
.../Electron.app/Contents/Resources/electron.icns

然后终端直接回到了:

perl 复制代码
user@mac my-app %

这里最奇怪的是:

没有:

javascript 复制代码
Error

没有:

复制代码
Failed

也没有正常结束时应该出现的:

复制代码
✔ Packaging application
✔ Making distributables

也就是说,最开始看起来像:

go 复制代码
Finalizing package 卡住

但打开完整 Debug 后才发现实际情况更像:

go 复制代码
Finalizing package
↓
Electron Packager 开始解压 Electron
↓
extract-zip 正常执行
↓
流程中途直接结束

八、检查退出码

为了判断是不是进程崩溃或者被 macOS 杀掉,继续执行:

ini 复制代码
DEBUG=* electron-forge make
echo "EXIT_CODE=$?"

结果:

ini 复制代码
EXIT_CODE=0

这个结果很反常。

一般来说:

复制代码
0

代表程序正常退出。

如果是被 SIGKILL,通常会出现类似:

复制代码
137

如果发生 segmentation fault,也通常不会是 0

但这里的情况却是:

diff 复制代码
Electron Forge 打包没有真正完成
+
没有 Error
+
EXIT_CODE=0

所以这也是为什么最开始会误以为它只是"卡住"。

实际上进程已经结束了,只是整个 Electron Forge make 流程没有完整执行到最后。


九、开始排查 Node.js 版本

继续检查版本后,当前组合是:

复制代码
Node.js          26.5.0
npm              11.17.0
Electron Forge   7.11.2
Electron Packager 18.4.4
Electron         44.0.0
macOS            M4 / arm64

由于:

  • Electron 下载正常
  • checksum 正常
  • Electron ZIP 能正常开始解压
  • 没有 Forge Error
  • 没有普通 Node Error
  • 退出码还是 0

于是开始把排查方向转向 Node.js 运行环境本身。


十、尝试切换到 Node.js 22

将 Node.js:

复制代码
26.5.0

切换为 Node.js 22。

然后重新安装项目依赖:

bash 复制代码
rm -rf node_modules
npm ci

清理之前的打包目录:

bash 复制代码
rm -rf out

重新执行:

go 复制代码
electron-forge make

这次 Electron Forge 可以正常继续执行后续流程,打包完成。

整个项目本身没有为了这个问题修改 Electron 代码,主要调整就是:

复制代码
Node.js 26
↓
Node.js 22

十一、给项目固定 Node.js 版本

对于 Electron 项目,建议固定开发和打包使用的 Node.js 版本,避免系统 Node 升级后再次出现类似问题。

项目根目录可以增加:

复制代码
.nvmrc

内容:

复制代码
22

以后进入项目后执行:

perl 复制代码
nvm use

即可切换到对应 Node.js 版本。

也可以在 package.json 中增加:

json 复制代码
{
  "engines": {
    "node": ">=22 <23"
  }
}

对于 Electron Forge 这类涉及:

java 复制代码
Node.js
Electron Forge
Electron Packager
Electron
native modules
asar
macOS 打包工具链

的项目,Node.js 版本也是打包环境的一部分。

如果以后再遇到类似:

go 复制代码
electron-forge make
↓
Finalizing package
↓
没有 Error
↓
DEBUG 日志执行到一半结束
↓
EXIT_CODE=0

除了检查 Forge 配置和 Electron 本身,也值得第一时间对比一下 Node.js 版本。

相关推荐
木木爱研究15 分钟前
elpis-里程碑四-基于Vue完成动态组件库建设
前端·后端
深念Y18 分钟前
Nuxt 项目 Docker 构建:从 pnpm+node 迁移到全 bun
java·前端·docker
qq_4260039619 分钟前
UI自动化元素定位不到解决方案
前端·pycharm·自动化
EthanChou202025 分钟前
AES67协议笔记
前端·笔记·es6
马优晨27 分钟前
pom.xml 中 jquery webjars 依赖解释
xml·前端·jquery·jquery webjars·webjars依赖
里欧跑得慢42 分钟前
AI 驱动的 UI 国际化方案自动适配:从单一语言到多语言布局的智能转换
前端·css·flutter·web
DolitD43 分钟前
云流技术深度剖析:单服务器下如何实现3D应用的多实例并发?
java·服务器·前端·3d·云原生·云计算
芦柑4641 小时前
画布和3D导演台工具:短剧分镜从素材整理到空间预演的完整链路
服务器·前端·数据库
李蚊子1 小时前
从代理提醒到真实响铃:懒熊闹钟的鸿蒙开发实践
前端·harmonyos