12k
All articles

打包与分发 Electron 应用

Electron Forge 与 electron-builder 指南:讲解打包、代码签名、公证、自动更新,以及用 GitHub Actions 发布 macOS、Windows、Linux。

OpenReplay Team
OpenReplay Team
打包与分发 Electron 应用

将 Electron 应用交付给真实用户是一个四阶段流水线:将应用打包为平台原生安装程序、对其进行签名与公证以获得操作系统信任、通过用户可访问的渠道进行分发,以及接入自动更新以保持版本最新。选择运行该流水线的工具是第一个决策,到 2026 年,这一决策归结为两个选项:Electron Forge 或 electron-builder。本指南将带你走完完整流程,包含可直接复制粘贴的配置、2023 年和 2024 年变更的代码签名规则,以及一个可在三个平台上并行构建的 GitHub Actions 矩阵——因为你无法在单台机器上完成所有平台的交叉构建。

核心要点

  • 截至 2026 年 6 月,Electron Forge 是官方维护的分发工具;其他工具由 Electron 社区成员维护,不提供 Electron 项目的官方支持——而 electron-builder 仍是下载量最高的替代方案,并内置了自动更新器。
  • 大多数团队容易搞错的依赖链:macOS 上的自动更新要求应用必须经过签名——这是 Squirrel.Mac 的强制要求,因此代码签名 → 公证 → 静默更新正常运行是一条不可断裂的链条。
  • Apple Developer Program 的费用为每年 99 美元,或在支持本地货币的地区以当地货币计价,成为会员后可免费对 Mac 应用进行公证
  • 不要再购买 EV 证书来跳过 SmartScreen:EV 证书此前可在首次下载时完全绕过 SmartScreen,但该行为已于 2024 年被移除,EV 签名的文件现在与 OV 证书走相同的信誉积累流程
  • 你无法在本地完成所有平台的交叉构建,因此现实可行的方案是使用 GitHub Actions 矩阵,分别运行 macos-latestwindows-latestubuntu-latest,并通过加密环境变量注入签名密钥。

2026 年:Electron Forge 与 electron-builder 的选择

如果你想要一个官方支持的一体化流水线,选择 Electron Forge;如果你想要最成熟的内置自动更新器和最广泛的社区生态,选择 electron-builder。两者都能为 macOS、Windows 和 Linux 生成经过签名、支持更新的安装程序。两者的差异在于支持模式和设计理念,而非功能能力。

Electron Forge 是 Electron 项目官方认可的工具。它是一个用于打包和分发 Electron 应用的一体化工具,将众多单一用途的包整合为一个开箱即用的完整构建流水线,涵盖代码签名、安装程序生成和产物发布。Forge 已将旧版的 @electron/packager@electron/osx-sign 工具整合到其 Makers 和 Publishers 系统中。值得注意的是,如果你不想使用 Electron Forge,其他第三方工具均由 Electron 社区成员维护,不提供 Electron 项目的官方支持

electron-builder 是那个社区替代方案——也是下载量更高的一个,根据不同统计口径,每周安装量在 200 万到 300 万次之间。截至 2026 年 6 月,当前稳定版本为 26.15.3,每月发布多个新版本,因此建议锁定版本号并在每个发布周期前重新检查。下一个主要版本 v27 截至 2026 年 6 月处于 alpha 阶段(27.0.0-alpha 系列):它将 electron-builder 迁移至原生 ES 模块,将最低运行时要求提升至 Node.js 22.12,并移除了长期废弃的 API,因此在采用之前需要进行 Node 版本和配置检查——但目前稳定渠道仍为 26.x。许多团队选择它的原因是其集成的更新器:electron-builder 是一个完整的解决方案,只需添加单个依赖,内部管理其他所有依赖,并以自定义实现替代了 Electron 维护者提供的功能——例如自动更新器。

本文使用 electron-builder 作为配置示例,因为其声明式的 package.json 配置块能清晰地映射到每个平台目标,且其配套的 electron-updater 是自托管更新的事实标准。如果你更倾向于使用官方路线,这些概念同样适用于 Forge。

Tauri 怎么样?

当约 100 MB 的包体积成为不可接受的限制时,Tauri 2.x 是 Electron 的一个可信的轻量级替代方案。它通过操作系统原生 WebView 渲染 UI,而不是打包完整的 Chromium 运行时,从而产生显著更小的二进制文件(数量级上的差异,而非精确比较)。但这种权衡是真实存在的:你将失去 Electron 跨机器一致的渲染效果及其庞大的 npm 和原生模块生态,同时还需要接受不同用户操作系统上 WebView 版本碎片化的问题。Tauri 适合小型、对安全敏感的工具类应用;当 UI 保真度和生态深度比磁盘占用更重要时,Electron 仍然占优。

使用 electron-builder 进行各平台打包

electron-builder 通过 package.json 中的单个 build 配置块生成原生安装程序。定义一个顶层配置,并为每个平台添加 macwinlinux 键,指定所需的目标格式。一个最简化的多平台配置如下所示:

{
  "build": {
    "appId": "com.example.myapp",
    "productName": "MyApp",
    "directories": { "output": "dist" },
    "files": ["dist-app/**/*", "package.json"],
    "mac": {
      "category": "public.app-category.productivity",
      "target": ["dmg", "zip"],
      "hardenedRuntime": true,
      "notarize": true
    },
    "win": {
      "target": ["nsis"]
    },
    "linux": {
      "target": ["AppImage", "deb", "rpm"],
      "category": "Utility"
    },
    "publish": [{ "provider": "github" }]
  }
}

每个目标对应一种真实的安装程序格式:

平台目标格式适用场景
macOSdmgpkgzipDMG 是标准的拖拽到应用程序文件夹的镜像格式;PKG 可运行安装前/后脚本,适合企业部署;zip 是 Squirrel.Mac 自动更新的必要格式
WindowsnsismsiportableNSIS 是支持用户级/机器级安装和卸载程序的可定制向导安装包;MSI 适合 GPO/Intune 部署;portable 无需安装即可运行
LinuxAppImagedebrpmsnapflatpakAppImage 是单一自包含可执行文件;deb/rpm 与 apt/dnf 集成;Snap 和 Flatpak 通过各自的应用商店分发

有两个 electron-builder 目标细节容易让人踩坑。macOS 上的 zip 目标在启用自动更新时并非可选项:macOS 的 zip 目标是 Squirrel.Mac 的必要条件,否则无法生成 latest-mac.yml,从而导致 autoUpdater 报错——由于 macOS 的默认目标已是 dmg+zip,通常无需显式指定。对于自动更新而言,macOS 应用必须经过签名才能正常工作,支持的默认目标格式为 DMG(macOS)、AppImage/DEB/Pacman/RPM(Linux)和 NSIS(Windows)。使用 npx electron-builder --mac --win --linux 执行构建,但请注意,你只能在对应平台上(或针对对应平台)完整构建经过签名的安装程序——这正是 CI 的重要性所在。

关于安全基线:本文假设你的应用已采用 Electron 推荐的安全配置——使用 preload 脚本,启用 contextIsolation,禁用 nodeIntegration。切勿以相反的配置发布应用;打包并不能修复不安全的渲染进程。

代码签名与公证:不可断裂的依赖链

以下是导致 macOS 发布失败最多的规则:未签名的 macOS 应用可以通知用户有更新可用,但无法静默安装更新。 代码签名是公证的前提,公证是 macOS 自动更新正常运行的前提。macOS 上的自动更新要求应用必须经过签名——这是 Squirrel.Mac 的强制要求。跳过签名,整个下游链条将全面崩溃。

macOS:先签名,再公证

你需要一个 Apple Developer ID 证书,这需要成为 Apple 开发者计划会员。Apple Developer Program 的费用为每年 99 美元,注册时会显示本地货币价格——并非”99 欧元”,且公证已包含在内:成为 Apple Developer Program 会员后,你可以免费对 Mac 应用进行公证。自 macOS 10.15 Catalina 起,公证(Apple 的自动化恶意软件扫描)对于在 Mac App Store 以外分发的 Developer ID 应用已成为强制要求。

在 electron-builder 中,在 mac 配置块中设置 hardenedRuntime: truenotarize: true(如上所示),然后在构建时通过环境变量提供凭据——切勿将凭据存入代码仓库:

# macOS 签名证书(Base64 编码的 .p12 文件)及其密码
export CSC_LINK="$(base64 -i developer-id.p12)"
export CSC_KEY_PASSWORD="••••••"
# 公证凭据(App Store Connect API 或 Apple ID 专用密码)
export APPLE_ID="you@example.com"
export APPLE_APP_SPECIFIC_PASSWORD="abcd-efgh-ijkl-mnop"
export APPLE_TEAM_ID="XXXXXXXXXX"

Windows:2024 年 SmartScreen 规则重置

在做 Windows 相关决策时,首先要了解几乎所有旧版指南都遗漏的这一变化。EV 证书不再能绕过 SmartScreen:几年前,使用扩展验证证书签名可以默认获得 SmartScreen 的正面信誉,但该行为已不复存在,仅为避免 SmartScreen 警告而支付 EV 溢价已不再合理。EV 签名的安装程序现在与更便宜的组织验证(OV)证书一样,需要通过相同的下载信誉积累过程。

另一个变化是私钥的存储要求。自 2023 年 6 月 1 日起,代码签名私钥必须存储在经过认证的硬件设备上——这正是 USB 令牌 OV 证书在无头 CI 环境中无法使用的原因。Tauri 的 Windows 签名文档也标注了同样的分界点:其标准指南仅适用于 2023 年 6 月 1 日之前获取的 OV 证书,对于该日期之后获取的证书,他们建议参考证书颁发机构的硬件令牌流程。

2026 年最简洁的默认方案是完全绕过令牌问题。Azure Artifact Signing——前身为 Trusted Signing——是一项与 Azure 深度集成的完全托管的端到端代码签名服务。它从云端完成签名,无需 USB 令牌,可原生集成到 CI/CD 流水线中,并将密钥存储在 Microsoft 托管的 HSM 中。建议按以下优先级做出决策:

  1. 优先选择 Azure Artifact Signing。 它天然适配 CI 环境,且价格低廉(Microsoft 文档中记载,小型项目的按需计费方案约为每月 10 美元)。其可用地区目前限于美国、加拿大、欧盟和英国,个人开发者目前仅限美国和加拿大。
  2. 如果不在上述地区,选择 OV 证书,可从 DigiCert、Sectigo 或 GlobalSign 购买。OV 证书在 SmartScreen 信誉方面与 Azure Artifact Signing 功能等效。
  3. 保留已有的 EV 证书直至到期——如果你已经拥有 EV 证书,它仍然有效且可用于签名,但不要仅为避免 SmartScreen 警告而购买新的 EV 证书。

已签名 vs 未签名

已签名 + 已公证未签名
macOS 首次启动正常,Gatekeeper 验证通过显示”身份不明的开发者”拦截提示;需右键点击 → 打开绕过
Windows 首次下载显示 SmartScreen 警告,直至信誉积累完成显示 SmartScreen 警告,且无信誉继承
macOS 自动更新静默更新正常运行仅能通知用户——无法替换二进制文件
Mac App Store 资格具备不具备

对于熟悉绕过步骤的开发者受众,未签名构建是可以接受的。但对于非技术用户——以及任何在 macOS 上启用自动更新的应用——签名是不可妥协的要求。

使用 electron-updater 实现自动更新

electron-updater(electron-builder 的配套工具)以极少的代码量为你提供跨平台自托管更新能力。它开箱即支持 GitHub Releases、Amazon S3、DigitalOcean Spaces、Keygen 和通用 HTTP(S) 服务器,只需两行代码即可运行。常见用法如下:

const { autoUpdater } = require("electron-updater");

app.whenReady().then(() => {
  createWindow();
  autoUpdater.checkForUpdatesAndNotify();
});

调用 autoUpdater.checkForUpdatesAndNotify()——不要调用 setFeedURL,因为 electron-builder 在构建时会自动创建内部的 app-update.yml 文件。发布目标由构建配置中的 publish 块指定;将其指向 { "provider": "github" } 意味着推送标签会触发 CI,将产物上传到 GitHub Release,更新器会自动找到它们。在 macOS 上,这一行代码在构建未经签名和公证的情况下不会产生任何实际效果——与上一节中的依赖链相同。Linux 没有通用的自动更新机制;AppImage 更新可通过 electron-updater 实现,但 deb/rpm 用户需通过包管理器进行更新。

分发渠道

根据受众覆盖范围以及你希望保留的收益和信任程度来选择渠道:

  • 自有网站。 完全掌控,支持签名或未签名,无佣金,可通过 GitHub Releases 或 S3 直接与 electron-updater 配合使用。
  • GitHub Releases。 免费托管,版本历史记录完整,是自动更新集成阻力最小的路径。
  • Mac App Store。 增加应用曝光度,但需要沙盒化和审核,并收取 Apple 标准的 30% 佣金——符合条件的开发者可通过 App Store 小型企业计划降至 15%(年收益低于 100 万美元)。
  • Microsoft Store。 仅凭 SmartScreen 优势就值得考虑:通过 Microsoft Store 发布 MSIX 包意味着 Microsoft 会自动为你的包重新签名,用户永远不会看到 SmartScreen 警告,你也无需购买或续签证书。
  • Homebrew Cask。 通过向 casks 仓库提交 Pull Request,为 macOS 用户提供免费的、开发者友好的分发渠道——非常适合通过 brew install 触达技术用户。

有一个值得记住的实践细节:由于 Electron 渲染进程本质上是一个 Chromium 窗口,浏览器会话回放监控工具可以在打包后的桌面构建中无修改地运行,这是观察仅在打包或自动更新后才在用户机器上出现的 UI 回归问题的少数可行方式之一——例如原生菜单和托盘路径、文件对话框流程、签名构建的 CSP 差异——而这些问题在开发阶段使用 electron . 时从不出现。

使用 GitHub Actions 在 CI 中构建三个平台

你无法在本地完成所有平台的交叉构建:DMG 公证需要 macOS 工具链,签名的 Windows 安装程序需要 Windows 工具链。2026 年现实可行的方案是使用 GitHub Actions 矩阵,并行运行 macos-latestwindows-latestubuntu-latest,并通过加密环境变量注入签名密钥。以下是一个完整的 release.yml,在推送标签时触发构建和发布:

name: Release
on:
  push:
    tags: ["v*"]

jobs:
  release:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [macos-latest, windows-latest, ubuntu-latest]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: npm ci
      - name: Build, sign, and publish
        run: npx electron-builder --publish always
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          # macOS 签名 + 公证(仅在 macos-latest 上读取)
          CSC_LINK: ${{ secrets.MAC_CSC_LINK }}
          CSC_KEY_PASSWORD: ${{ secrets.MAC_CSC_KEY_PASSWORD }}
          APPLE_ID: ${{ secrets.APPLE_ID }}
          APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
          APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
          # Windows:Azure Artifact Signing 凭据(仅在 windows-latest 上读取)
          AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
          AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
          AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}

每个运行器仅构建其所属平台的目标格式,electron-builder 使用该运行器环境中存在的凭据进行签名,--publish always 将所有产物以及 latest*.yml 更新元数据上传到同一个 GitHub Release。将所有密钥存储在仓库或环境 Secrets 中——切勿写入工作流文件。由于 Azure Artifact Signing 通过普通环境变量与 GitHub Actions 和 Azure DevOps 集成,Windows 构建任务无需 USB 令牌,也无需自托管运行器。

发布一个 Electron 应用,与其说是执行某个神奇的命令,不如说是尊重这条依赖链:签名才能公证,公证才能让 macOS 自动更新正常运行,而整个流程必须在 CI 矩阵中运行,因为没有任何一台机器能够构建全部三个平台。配置好 build 块,添加 electron-updater,提交 release.yml,下次执行 git tag v1.0.0 && git push --tags,即可一次性为所有平台生成经过签名、支持更新的安装程序。

常见问题

我能在单台机器上为 macOS、Windows 和 Linux 构建经过签名的安装程序吗?

不能。DMG 公证需要 macOS 工具链,签名的 Windows 安装程序需要 Windows 工具链,因此没有任何一台机器能够为所有三个平台生成经过签名的构建产物。你可以为当前所在的平台进行构建,electron-builder 也支持部分交叉目标构建,但签名和公证是与平台绑定的。2026 年现实可行的方案是使用 GitHub Actions 矩阵,并行运行 macos-latest、windows-latest 和 ubuntu-latest,每个运行器仅构建并签名其所属平台的目标格式。

通过 Microsoft Store 发布是否可以在不购买代码签名证书的情况下消除 SmartScreen 警告?

是的。通过 Microsoft Store 发布 MSIX 包意味着 Microsoft 会自动为你的包重新签名,因此用户永远不会看到 SmartScreen 警告,你也无需购买或续签证书。这使得 Microsoft Store 成为完全跳过证书费用和信誉积累过程的有效途径。权衡之处在于需要经过商店提交、审核流程,并将应用打包为 MSIX 格式,而非直接从自有网站分发独立的 NSIS 或 MSI 安装程序。

为什么我的 macOS 应用能通知用户有更新,却从不自动安装?

构建几乎可以肯定是未签名的。在 macOS 上,应用必须经过签名才能实现自动更新,因为 Squirrel.Mac 对此有强制要求。未签名的应用可以检测到新版本并通知用户,但无法静默替换二进制文件。解决方法是完成完整的依赖链:获取 Apple Developer ID 证书,对应用进行签名,然后进行公证。代码签名是公证的前提,公证是 macOS 静默自动更新正常运行的前提。

为了避免 Windows 上的 SmartScreen 警告,购买 EV 证书还值得吗?

不值得。EV 证书此前可在首次下载时完全绕过 SmartScreen,但 Microsoft 已于 2024 年移除了这一即时信誉机制。EV 签名的安装程序现在与更便宜的组织验证证书一样,需要经历相同的下载信誉积累过程,因此仅为避免 SmartScreen 警告而支付 EV 溢价已不再合理。对于 2026 年的大多数团队而言,更简洁的默认选择是 Azure Artifact Signing——它从云端完成签名,无需 USB 令牌;如果不在其支持的地区,则选择 OV 证书。

DevTools for the frontend

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.