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

0 阅读5分钟

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 安装包,可以使用:

@electron-forge/maker-dmg

安装:

npm install --save-dev @electron-forge/maker-dmg

然后在 Forge 配置中加入:

{
  name: '@electron-forge/maker-dmg',
  platforms: ['darwin'],
  config: {},
}

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

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

node -v
npm -v
npx electron-forge --version

输出:

v26.5.0
11.17.0
7.11.2

确认当前架构:

node -p "process.arch + ' ' + process.platform"

输出:

arm64 darwin

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

直接执行:

electron-forge make

前面的流程都正常:

✔ Checking your system
✔ Loading configuration
✔ Resolving make targets
✔ Preparing to package application
✔ Running generateAssets hook
✔ Running prePackage hook

然后进入:

❯ Packaging application
❯ Packaging for arm64 on darwin
❯ Copying files
❯ Preparing native dependencies
❯ Finalizing package

最后一直停在:

Finalizing package

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

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

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

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

先尝试:

DEBUG=electron-forge:* electron-forge make

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

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

但是日志依然停在:

❯ Finalizing package

还不足以定位问题。


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

于是进一步执行:

DEBUG=* electron-forge make

这次可以看到:

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

等更底层的日志。

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

Electron Packager 18.4.4
Node v26.5.0
Host Operating system: darwin 25.5.0 (arm64)

Electron 版本:

Target Electron version: 44.0.0

目标平台:

Target Platforms: darwin
Target Architectures: arm64

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


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

日志中可以看到:

electron-packager Downloading Electron with options {
  "platform":"darwin",
  "arch":"arm64",
  "version":"44.0.0",
  "artifactName":"electron"
}

紧接着:

@electron/get:index Cache hit

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

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

Expected checksum:
076d79742986e1b100b69ebecc691cb07368045e54c9087cef631b8622b76a80

Actual:
076d79742986e1b100b69ebecc691cb07368045e54c9087cef631b8622b76a80

两个值完全一致。

因此当时基本排除了:

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

Electron 安装包本身没有异常。


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

接下来日志进入:

electron-packager Extracting electron-v44.0.0-darwin-arm64.zip

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

extract-zip zipfile entry Electron.app/
extract-zip extracting entry ...
extract-zip finished processing ...

包括各种 Electron 资源目录:

Electron.app/Contents/Resources/de.lproj/
Electron.app/Contents/Resources/ja.lproj/
Electron.app/Contents/Resources/zh_CN.lproj/

最后可以看到类似:

extract-zip zipfile entry Electron.app/Contents/Resources/electron.icns

以及:

extract-zip opening read stream
.../Electron.app/Contents/Resources/electron.icns

然后终端直接回到了:

user@mac my-app %

这里最奇怪的是:

没有:

Error

没有:

Failed

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

✔ Packaging application
✔ Making distributables

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

Finalizing package 卡住

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

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

八、检查退出码

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

DEBUG=* electron-forge make
echo "EXIT_CODE=$?"

结果:

EXIT_CODE=0

这个结果很反常。

一般来说:

0

代表程序正常退出。

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

137

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

但这里的情况却是:

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。

然后重新安装项目依赖:

rm -rf node_modules
npm ci

清理之前的打包目录:

rm -rf out

重新执行:

electron-forge make

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

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

Node.js 26
↓
Node.js 22

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

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

项目根目录可以增加:

.nvmrc

内容:

22

以后进入项目后执行:

nvm use

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

也可以在 package.json 中增加:

{
  "engines": {
    "node": ">=22 <23"
  }
}

对于 Electron Forge 这类涉及:

Node.js
Electron Forge
Electron Packager
Electron
native modules
asar
macOS 打包工具链

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

如果以后再遇到类似:

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

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