Electron 应用打包与自动更新

区分 package.json 和 forge.config.js 的职责,生成 Electron 应用并接入基础自动更新流程。

🎯 引言

开发时执行 npm start,运行的是项目源码。普通用户需要的是一个可以安装或直接打开的应用文件,所以发布前要把 Electron、页面代码和资源整理成应用包。

本篇只解决三个问题:

  • package.jsonforge.config.js 分别配置什么。
  • packagemake 分别生成什么。
  • 签名和自动更新在发布流程中解决什么问题。

🧱 两个配置文件,各自负责什么

先记住这张表:

文件负责内容本篇会写什么
package.json项目基本信息和命令应用名称、版本、入口文件、打包脚本
forge.config.jsElectron Forge 的打包规则应用图标、安装包格式、目标平台

应用名称和版本写在 package.json,打包时使用的图标和安装包格式写在 forge.config.js。两者不是同一个配置入口。

BrowserWindow 里的 icon 是运行时窗口图标,和安装包图标不是一回事。为了避免混淆,本篇不把它放进打包流程;初学项目只配置 Forge 的应用图标即可。


🧰 安装 Electron Forge

本篇示例使用 Node.js 24.x LTS、Electron 44.0.0 和 Electron Forge 7.11.2。在已有 Electron 项目中安装 Forge:

npm install --save-dev @electron-forge/cli@7.11.2
npx electron-forge import
Electron Forge 的命令行提示和配置文件会随版本更新。本文以 Forge 7.11.2 为例,实际操作时以项目安装的版本和官方文档为准。

导入完成后,项目通常会增加下面三个命令:

package.json
{
    "scripts": {
        "start": "electron-forge start",
        "package": "electron-forge package",
        "make": "electron-forge make"
    }
}

✍️ 配置 package.json

package.json 只写应用的基本身份信息:

package.json
{
    "name": "electron-course",
    "productName": "Electron Course",
    "version": "1.0.0",
    "description": "一个 Electron 学习项目",
    "author": "Your Name",
    "main": "main.js",
    "scripts": {
        "start": "electron-forge start",
        "package": "electron-forge package",
        "make": "electron-forge make"
    }
}

这里最容易混淆的是:本篇不在 package.json 中写 icon 应用图标由下面的 forge.config.js 配置。


⚙️ 配置 forge.config.js

在项目根目录创建 forge.config.js

forge.config.js
module.exports = {
    packagerConfig: {
        icon: './assets/icon',
    },
    makers: [
        {
            name: '@electron-forge/maker-zip',
            platforms: ['darwin'],
        },
        {
            name: '@electron-forge/maker-squirrel',
            platforms: ['win32'],
        },
        {
            name: '@electron-forge/maker-deb',
            platforms: ['linux'],
        },
    ],
};

这段配置只看两部分:

1. packagerConfig.icon

packagerConfig: {
    icon: './assets/icon',
}

它告诉 Forge 去 assets 目录寻找应用图标。这里写不带扩展名的路径,Forge 会根据目标系统寻找对应格式的图标文件:

assets/
├── icon.ico    # Windows
├── icon.icns   # macOS
└── icon.png    # Linux

这配置的是打包后应用使用的图标,不是 Vue 页面里的图片,也不是窗口运行时动态设置的图标。

2. makers

makers 决定 npm run make 要生成什么格式的分发文件:

maker目标系统作用
maker-zipmacOS生成 zip 压缩包
maker-squirrelWindows生成 Windows 安装程序
maker-debLinux生成 .deb 安装包

不需要发布某个系统时,可以先删掉对应的 maker。初学时只在当前系统生成一种产物更容易检查。


📦 package 和 make 的区别

先执行:

npm run package

package 会把源码、页面和 Electron 运行时整理成一个可以启动的应用目录。它适合先验证:

  • 应用能不能启动。
  • 页面资源路径是否正确。
  • 图标和应用名称是否生效。

确认应用目录可以运行后,再执行:

npm run make

make 会使用 makers 配置,把应用目录进一步制作成安装程序或压缩包,供用户安装或分发。

所以可以这样记:

package:整理出一个能运行的应用
make:把这个应用做成方便交付的文件

🔏 签名先了解什么

签名的作用是告诉操作系统:这个应用是谁发布的,并且安装包发布后没有被修改。

完整的签名流程会在下一篇单独讲解。本节只需要知道:正式发布时要准备平台证书,Forge 负责在打包过程中使用证书;没有证书时,学习阶段可以先跳过签名。

可以这样区分:

目标本节能帮你完成什么
本地学习可以不签名,先完成打包
本地验证签名配置证书后,使用 Forge 签名并检查结果
对外发布还需要证书申请、公证、安装包测试和安全保存凭证

macOS:在 Forge 中开启签名

你需要先准备:

  1. Apple Developer Program 账号。
  2. 安装到当前 Mac 的 Developer ID Application 证书。
  3. Xcode 命令行工具。

先检查 Mac 是否能找到签名证书:

security find-identity -p codesigning -v

然后在已有的 packagerConfig 中加入 osxSign: {}

forge.config.js
module.exports = {
    packagerConfig: {
        icon: './assets/icon',
        osxSign: {},
    },
};

osxSign: {} 的意思是:让 Forge 使用当前 Mac 已安装的签名证书给应用签名。之后执行:

npm run package

如果签名成功,生成的 macOS 应用就带有代码签名。可以用下面的命令检查:

codesign --verify --deep --strict --verbose=2 \
    out/electron-course-darwin-arm64/Electron\ Course.app

macOS 对外发布通常还需要公证。公证需要 Apple 账号或 App Store Connect API Key,凭证应放在环境变量或钥匙串中,不要写进 forge.config.js 并提交到代码仓库。

所以 macOS 对外发布至少要完成:Developer ID Application 签名、打包、提交 Apple 公证、公证通过后再分发。只执行 npm run package 并不等于已经完成面向用户的 macOS 发布。

Windows:给安装程序配置证书

Windows 签名需要代码签名证书文件,例如 .pfx,以及证书密码。把证书配置到 Windows maker 中:

forge.config.js
module.exports = {
    makers: [
        {
            name: '@electron-forge/maker-squirrel',
            config: {
                certificateFile: process.env.WINDOWS_CERTIFICATE_FILE,
                certificatePassword: process.env.WINDOWS_CERTIFICATE_PASSWORD,
            },
        },
    ],
};

在 Windows PowerShell 中临时提供环境变量,再生成安装程序:

$env:WINDOWS_CERTIFICATE_FILE = 'C:\certs\electron-course.pfx'
$env:WINDOWS_CERTIFICATE_PASSWORD = '证书密码'
npm run make
证书文件和密码都属于敏感信息,不要提交到 Git。Apple、Microsoft 和证书服务商的申请页面会更新,申请证书时以当前平台要求为准。

Windows 对外发布还要确认签名覆盖了最终分发的安装程序,并在没有开发环境的干净 Windows 机器上测试安装、启动和卸载。证书类型、时间戳服务和 SmartScreen 提示也属于 Windows 发布流程的一部分。

因此,本文步骤可以完成“Forge 使用证书签名”的核心操作,但不能替代平台证书申请、macOS 公证和正式发布检查。


🔄 如何实现自动更新

这里选择一条适合入门的路径:公开 GitHub 仓库 + GitHub Releases + update-electron-app

这条路径的完整过程是:

Forge 生成安装包
    ↓
发布到 GitHub Release
    ↓
应用启动时检查 Release
    ↓
发现新版本后下载并提示重启

这条方案有几个前提:应用运行在 macOS 或 Windows,代码发布在公开 GitHub 仓库,构建文件发布到 GitHub Releases;macOS 应用还必须签名。Linux 不使用 Electron 内置自动更新,通常由 Linux 发行版的软件包管理器负责更新。

第一步:安装更新依赖

本篇使用 update-electron-app 3.3.0 和 Forge GitHub Publisher 7.11.2

npm install update-electron-app@3.3.0
npm install --save-dev @electron-forge/publisher-github@7.11.2

第二步:在 package.json 写仓库地址

更新工具需要知道应用对应哪个 GitHub 仓库:

package.json
{
    "repository": {
        "type": "git",
        "url": "https://github.com/你的用户名/electron-course.git"
    }
}

把示例地址换成自己的公开仓库地址。

第三步:配置 GitHub Publisher

forge.config.js 中加入 publishers

forge.config.js
module.exports = {
    publishers: [
        {
            name: '@electron-forge/publisher-github',
            config: {
                repository: {
                    owner: '你的 GitHub 用户名',
                    name: 'electron-course',
                },
            },
        },
    ],
};

第四步:在主进程启动自动更新

main.js 顶部加入:

main.js
const { updateElectronApp } = require('update-electron-app');

updateElectronApp();

这行代码会让应用启动时检查更新,发现新版本后在后台下载,并提示用户重启安装。它不会在开发环境的 npm start 中产生有意义的更新结果,必须测试打包后的应用。

第五步:发布新版本

先把 package.json 的版本从 1.0.0 改成 1.0.1,再配置 GitHub Token:

export GITHUB_TOKEN='你的 GitHub Token'
npx electron-forge publish

Windows PowerShell 使用:

$env:GITHUB_TOKEN = '你的 GitHub Token'
npx electron-forge publish

Forge 会生成当前系统的分发文件并上传到 GitHub Release。旧版本应用下次启动时就能检查到新版本。

GitHub 仓库、Release 页面和 Token 权限设置会随平台界面变化。Token 不要写入代码或提交到 Git,实际发布时以 GitHub 和 Electron Forge 当前文档为准。

🧾 小节总结

  • package.json 保存应用信息、入口文件和命令。
  • forge.config.js 保存 Forge 的打包规则和安装包格式。
  • packagerConfig.icon 配置打包应用图标,不需要在 package.json 重复配置。
  • package 生成可运行的应用目录,make 生成可分发文件。
  • macOS 通过 packagerConfig.osxSign 开启签名,Windows 在 maker 中配置证书文件和密码。
  • GitHub Releases 配合 update-electron-app,可以让 macOS 和 Windows 应用检查并下载新版本。

❓ 知识问答

Q1:为什么 package.json 示例里没有 icon

A:因为本篇使用 Forge 配置图标,图标写在 forge.config.jspackagerConfig.icon 中。

Q2:packagemake 都要执行吗?

A:建议先执行 package 检查应用能否启动,再执行 make 生成分发文件。

Q3:学习 Electron 必须配置签名和自动更新吗?

A:不需要。学习阶段可以先完成 packagemake;正式分发时,再准备证书和更新发布环境。

Q4:为什么自动更新不能只在 npm start 时测试?

A:自动更新检查的是已发布的安装包和版本号,开发环境没有对应的 Release 文件,所以要用打包后的旧版本和新版本测试。

🧪 小练习

练习一:在 package.json 中把应用名称改成自己的名称。

练习二:在 forge.config.js 中只保留当前系统对应的一个 maker,并执行:

npm run package
npm run make

观察 out 目录中分别出现了什么产物。

练习三:如果你有公开 GitHub 仓库,按照本文补充 repository、Publisher 和 updateElectronApp(),先完成一次测试 Release。

🎉 现在你已经分清了项目基本信息、Forge 打包规则、应用目录和分发文件之间的关系。