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 版本。

相关推荐
xy34531 分钟前
Axure 9.0 中继器核心结构
前端·ui·html·axure·原型·产品设计
老王以为8 分钟前
走进 AI Agent 第四篇(上):知识获取管道——RAG 基础
前端·人工智能·全栈
夏天要喝冰可乐20 分钟前
一处写作,多平台分发:我给掘金做了一款开源 Chrome 插件
前端·chrome·vibecoding
货拉拉技术31 分钟前
货拉拉开源Hadice:安卓 & 鸿蒙桌面调试工具
前端
程序猿DD1 小时前
OctaFuse Gateway 2.11.0:流式请求优化、用户折扣策略与错误契约升级
前端·后端
尾善爱看海1 小时前
《JavaScript 数组操作全攻略:12 类 API + 30 个实战场景 + 20 个避坑指南》
前端·javascript·面试
计算机魔术师1 小时前
Anthropic 估值冲 4 万亿,但企业客户已经偷偷换了便宜模型
前端
王六米。2 小时前
RAG知识库建设 文档解析 切分与索引如何衔接
服务器·前端·网络·企业数字化转型·智钳智能盒子
名字还没想好☜2 小时前
React 文件上传实战:预览 URL 回收、多文件逐个进度与拖拽放置区踩坑
前端·react·next.js
console.log('npc')2 小时前
06 — Model 层:数据模型与操作
前端·后端·node.js·express