@flun/desktop-builder

中文文档
6.6.2发布于 2026/11/13ISCTypeScriptES Module近 30 天下载 2564

将任意 Node.js 网站一键打包为当前桌面应用('win', 'mac', 'linux')(基于 Electron),支持高度自定义配置;

中文使用文档
文档目录47 节
  1. 简介
  2. 特性
  3. 包目录结构
  4. 安装前准备
  5. 允许安装脚本执行
  6. 下载依赖(Windows)
  7. 安装
  8. 命令行
  9. 函数方式
  10. 参考配置
  11. 配置总览
  12. 1. 基础字段
  13. 2. 窗口配置 ( window )
  14. 3. 菜单配置 ( menu )
  15. 4. 打包配置 ( build )
  16. 5. 高级选项 ( advanced )
  17. 6. 允许安装脚本 ( allowScripts )
  18. 7. 排除规则
  19. 8. node_modules 优化 ( optimize )
  20. 9. 调试构建 ( --debug )
  21. 代码签名
  22. 一,Windows 应用本体签名 ( build.win.sign )
  23. 二,Windows 安装程序与卸载程序签名 ( build.inno )
  24. 三,macOS 签名与公证 (mac.notarize)
  25. 四,Linux 包签名
  26. 五,生成并信任自签名测试证书
  27. 关于网络依赖与构建性能
  28. 默认行为:构建时打包依赖
  29. 如何回退到运行时安装依赖(旧行为)
  30. 优化建议
  31. 进一步定制
  32. 1. 直接使用 electron-builder 配置字段
  33. 2. 使用钩子脚本
  34. 3. 修改主进程模板(高级)
  35. 4. 自行调用 electron-builder
  36. 常见问题
  37. 1. 构建时提示 desktopAppConfig.js not found
  38. 2. 构建失败,提示 electron-builder 相关错误
  39. 3. 应用版本号如何设置?
  40. 4. 生成的安装包很大(约 100MB+)
  41. 5. 我的 excludeFiles 中的规则在打包阶段也生效了,如何避免?
  42. 6. Windows 安装程序为什么使用 Inno Setup 而不是 NSIS?
  43. 7. 旧版 desktopAppConfig.js 在 electron-builder v27 下报错怎么办?
  44. 8. 构建或运行异常,怀疑是优化系统引起的,怎么排查?
  45. 9. 构建速度变慢了,是正常的吗?
  46. 许可证
  47. 贡献

@flun/desktop-builder

将任意 Node.js 项目一键打包为当前平台的桌面应用 (Windows, macOS, Linux)(基于 Electron),支持高度自定义配置;

npm version license node


简介

@flun/desktop-builder 是一个 将本地 Node.js 项目打包成桌面安装包 的构建工具;您只需提供一个配置文件,即可生成 Windows(基于 Inno Setup 的安装程序),macOS(DMG/ZIP)或 Linux(AppImage/Deb/RPM 等)安装程序;

核心机制:

  • 该工具会将您的 Node.js 项目(含所有业务代码,资源文件与依赖)与 Electron 前端整合,打包为一个独立的桌面应用;

  • Electron 本身内置了 Node.js 运行时,因此打包后的应用在启动时,会使用自带的 Node.js 运行您的 Node.js 项目;

  • 最终用户无需在电脑上安装 Node.js 或任何其他运行时环境,双击桌面图标即可直接使用;

  • 本包采用 ESM 书写(package.json 中 "type": "module"),包括 postinstall 自动复制到你项目根目录的示例 desktopAppConfig.js, 如果你的项目为 CJS 请修改导出方式为 module.exports = { ... };

关于 asar 打包:本工具不支持也不建议启用 ASAR 打包(electron-builder 的 asar 配置);原因如下:

  • 本工具的运行架构是"Electron 主进程 + 独立 Node.js 子进程":主进程通过 child_process.spawn 启动一个 Node 进程来运行您的 Node.js 项目;
  • 外部 Node 进程不加载 Electron 的 fs 补丁,无法读取 asar 归档内的文件;同时 asar 虚拟路径也不能作为子进程的工作目录(Windows 的 CreateProcess 会直接报 ENOENT);
  • 因此启用 asar 后,Node.js 子进程会启动失败(表现为应用启动后立即退出,页面 ERR_CONNECTION_REFUSED);
  • 本工具已在 build.js 中显式设置 asar: false,确保打包后的 resources/app 始终是真实目录结构;

我们的替代方案:asar 的核心诉求是"把成千上万个小文件打成单文件,减少启动时文件系统 I/O 与杀毒软件扫描量,从而加快启动";但 asar 用虚拟归档实现,牺牲了 Node.js 子进程的读取能力--它没有真正解决问题,只是把问题从"慢"换成了"打不开"; 本工具给出不破坏目录结构的等价方案:

  • 构建时自动执行 node_modules 优化系统(详见 特性),把包内 JS 按入口合并成单文件(bundled/index.mjs / index.cjs),同时清理平台二进制,开发文件等非运行文件;
  • 打包后的 resources/app 仍是真实目录结构,Node.js 子进程可正常读取,不触发 asar 的兼容性问题;
  • 构建时自动判断并执行三种动作:重新安装依赖+优化(依赖清单变化 / 上次构建未完成 / 运行环境变化 / 缓存目录缺失 / 优化由开转关 / 优化程序更新 / 原生编译由关转开),仅需优化(优化由关转开),跳过安装与优化(其余情况, 含单独的原生编译由开转关).判断依据记录在 .deps-snapshot.json(依赖,平台,架构,优化开关,原生编译开关,优化代码指纹, 上次构建是否成功),每次动作与原因均打印在日志中;这保证了每次构建产物一致,同时二次构建零开销;
  • 一句话对比:asar 减小了文件数但子进程打不开;本工具在保持真实目录结构的前提下,同样大幅减小文件数,加速启动;

asar 残留:v5.1.4 之前曾支持 asar,可能留下不完整的 node_modules;当前机制在升级后首次构建会自动重装恢复,无需手动处理;


特性

  • 一键打包:基于 electron-builder 和 Inno Setup 等,快速生成当前平台的安装包;
  • 高度可配置:通过单一 desktopAppConfig.js 控制窗口,图标,菜单,安装选项,签名,压缩等;
  • 跨平台支持:Windows,macOS,Linux(仅构建当前运行平台,但支持输出多种格式);
  • 自带 Node.js 运行时:你的 Node.js 项目将由 Electron 内置的 Node.js 接管,不再依赖外部安装;
  • 灵活的安装选项:Windows 使用 Inno Setup(支持自定义向导样式,语言,快捷方式等),macOS 支持 DMG/ZIP,Linux 支持 AppImage/Deb 等;
  • 品牌自定义:应用图标,安装/卸载图标,DMG 卷宗图标,背景图片,向导图片等;
  • 菜单自定义:完全自定义应用菜单(语言,角色,点击回调,甚至内联函数);
  • 精细排除:可排除不需要的文件,依赖包和最终输出文件(excludeFiles 同时在复制和打包阶段生效);excludeDependencies 用于自定义排除生产依赖包(如平台专用包,已确认无用的包);
  • 可扩展:允许直接添加 electron-builder 和 Inno Setup 任意扩展字段;
  • 依赖预打包:构建时自动判断是否安装生产依赖并打包进应用,用户首次启动无需联网,开箱即用;
  • 主题切换支持:通过菜单配置轻松切换浅色/深色/跟随系统主题;
  1. 清开发文件:删除 .md / .map / .d.ts / .ts / .cts / .mts / .h / .c / .gyp / .vcxproj / .tlog / .obj / .lib / .pdb / tsconfig.json / .nycrc / .editorconfig / package-lock.json 等非运行文件;递归进入嵌套 node_modules,清理多层依赖中的同类文件;原生模块编译已在优化前完成,编译类文件与 node-gyp 中间产物一律清理,仅保留 .node;
  • 优化的逃生舱口:若遇异常,可在 desktopAppConfig.js 中 optimize: { enabled: false } 整体关闭,或 optimize: { exclude: ["包名"] } 排除优化时异常或不想优化的包;
  • 卸载自动清理:卸载时自动终止进程,删除应用生成的同名防火墙规则,清空安装目录;可选删除用户数据, 并据此保留或清除安装目录记忆(usePreviousAppDir);
  • 可选加入 Windows Defender 排除项(默认勾选):安装向导新增"选择附加任务"页,默认勾选"将应用加入 Windows Defender 排除项,加快启动"--排除后应用启动不再被实时扫描,冷启动更快;如不需要可在安装时取消勾选(代价:每次开机首次启动稍慢);仅 Windows 生效;

包目录结构

包结构如下(也可参考项目根目录被自动复制出的文件):

@flun/desktop-builder/
├── bin/
│   └── cli.js                    # 命令行入口
├── build/                        # 默认资源(图标,安装向导图)
│   ├── icon.png                  # 应用图标(512×512 PNG,跨平台默认)
│   ├── setup.ico                 # Windows 安装程序图标
│   ├── uninstallerIcon.ico       # Windows 卸载程序图标
│   ├── wizard.bmp                # Inno Setup 左侧大图(164×314 BMP)
│   └── wizardSmall.bmp           # Inno Setup 右上小图(55×58 BMP)
├── build.js                      # 构建主逻辑(复制,依赖,优化,electron-builder,Inno Setup)
├── copy-files.js                 # postinstall:复制配置模板与 build/ 到项目根
├── desktopAppConfig.js           # 配置文件模板(安装时复制到项目根)
├── electron-main.js              # Electron 主进程模板(构建时生成 main.mjs)
├── index.js                      # 库入口,导出 build
├── optimize-node-modules.js      # node_modules 优化系统(6 阶段)
├── index.d.ts                    # TypeScript 类型声明
├── CHANGELOG.md                  # 更新日志
├── README.md                     # 本文件
└── LICENSE                       # 许可

安装前准备

允许安装脚本执行

本包在安装时可能触发某些依赖包的自动脚本(如 postinstall 等);如果你的 npm 全局配置或项目配置禁止了脚本执行(例如设置了 ignore-scripts=true),可能会导致安装不完整或运行时异常;

推荐在项目根目录的 package.json 中添加 allowScripts 字段,显式放行本包及其依赖的脚本:

{
  "allowScripts": {
    "esbuild": true,
    "@flun/desktop-builder": true
    // 如果依赖的其它包(如 bcrypt,electron-winstaller 等)也有脚本,请按需添加,格式相同
  }
}

下载依赖(Windows)

  1. 大部分情况下无需手动下载,构建时自动下载安装;
  2. 安装版手动安装时一定要选择默认安装路径,不然会因为找不到文件而构建失败;
  3. 如果你是在中国下载的便携版压缩文件,请解压到 "C:\Users\你的用户名.electron-builder-cache" 下(Windows);

安装

在你的项目目录下安装为开发依赖:

npm install -D @flun/desktop-builder

安装完成后,postinstall 脚本会自动将 desktopAppConfig.js 配置文件模板以及 build/ 目录(含默认图标等资源)复制到你的项目根目录(如果不存在);


命令行

包内声明 bin 为 desktop-builder,安装后可直接调用:

desktop-builder build          # 按 desktopAppConfig.js 构建桌面应用
desktop-builder build --debug  # 输出详细日志(优化阶段每个包的处理、electron-builder 完整输出)
desktop-builder example        # 生成 desktopAppConfig.js 与 build/ 到项目根
desktop-builder clean          # 清理临时构建目录
desktop-builder help           # 查看用法
命令/参数作用
build构建桌面应用,产物输出到 build.outputDir(默认 ./dist)
example生成 desktopAppConfig.js 与 build/ 到项目根目录
clean清理临时构建目录
--debug输出详细日志,便于排查构建问题
--help、-h、help显示用法

项目内安装时用 npx desktop-builder;未指定命令时等同 help;未知命令会先打印帮助内容,再以非零码退出;

使用前先执行 npx desktop-builder example,按需修改生成的 desktopAppConfig.js(必填字段见 参考配置),然后执行:

npx desktop-builder build

首次运行会下载 Electron 运行时(约 100MB),请耐心等待;构建完成后,安装包输出到 ./dist (可通过 build.outputDir 自定义);


函数方式

除命令行外,也可在代码中直接调用 build():

import { build } from '@flun/desktop-builder';
await build();

参考配置

所有配置集中在项目根目录的 desktopAppConfig.js 中,本工具会在构建时读取该文件;配置对象按功能划分为以下几个顶层字段, 各字段的作用如下表;每个字段的详细配置见后续对应章节;

说明:本工具的所有配置对象(window / menu / build 及其子对象)均支持扩展--除了本章节列出的常用字段, 你还可以直接添加 electron-builder,Inno Setup 等官方支持的其他字段;工具会原样合并到最终的 builder.json / .iss 脚本中;

配置总览

  • serverPath (string):必填,Node.js 项目入口文件路径(相对于项目根目录);详见 1. 基础字段
  • appUrl (string):必填,应用启动后访问的地址(如 http://localhost:7296);详见 1. 基础字段
  • appName (string):应用显示名称(标题栏,快捷方式,安装程序等);详见 1. 基础字段
  • enableLogging (boolean):是否启用日志文件(调试用);详见 1. 基础字段
  • window (object):主窗口外观与行为;详见 2. 窗口配置
  • menu (array):应用菜单模板(语言,角色,点击回调);详见 3. 菜单配置
  • build (object):打包配置(应用标识,输出目录,图标,安装选项,签名等);详见 4. 打包配置
  • advanced (object):Node.js 子进程启停行为;详见 5. 高级选项
  • allowScripts (object):构建阶段放行安装脚本的包名列表;详见 6. 允许安装脚本
  • excludeFiles (string[]):复制项目文件时排除的文件/目录;详见 7. 排除规则
  • excludeDependencies (string[]):从最终依赖列表中移除的 npm 包;详见 7. 排除规则
  • excludeOutputs (string[]):从最终输出目录中排除的文件;详见 7. 排除规则
  • optimize (object):优化配置(enabled 开关,exclude 排除异常或不想优化的包); 详见 8. optimize

build 子字段概览:

  • build.appId / outputDir / publisher / shortcutName / nativeModules:通用打包配置; 详见 4.1 通用字段
  • build.win:Windows 平台配置;详见 4.2 Windows
  • build.inno:Windows Inno Setup 安装程序;详见 4.3 Inno Setup
  • build.mac / build.dmg:macOS 应用与 DMG 卷宗;详见 4.4 macOS 与 DMG
  • build.linux:Linux 应用与包格式;详见 4.5 Linux

签名相关的操作(证书生成,信任配置,各平台签名细节)统一在 代码签名 章节说明;


1. 基础字段

作用:定义应用的基本信息和启动入口;

export default {
  serverPath: './server.js',           // 项目入口(相对项目根目录)
  appUrl: 'http://localhost:7296',     // 应用访问地址
  appName: '我的应用',                  // 应用显示名称(不填则从 package.json 的 name 读取)
  enableLogging: false,                // 是否启用日志(写入桌面 myapp_debug.log)
};
  • serverPath(必填):Node.js 项目的入口文件路径;
  • appUrl(必填):Electron 主窗口加载的地址,也就是你 Node.js 项目的访问地址;若使用 HTTPS,需填写 https://...;
  • appName:应用显示名称,用于窗口标题,快捷方式,安装程序等;不填时默认从 package.json 的 name 读取;若 name 也没有, 则回退为 deskApp;
  • enableLogging:调试开关;设为 true 时,主进程和子服务的运行日志会写入桌面的 myapp_debug.log,便于排查启动问题;默认 false;

2. 窗口配置 (window)

作用:控制 Electron 主窗口的外观,尺寸,行为以及内部渲染进程的 webPreferences;

window: {
  width: 1200,                    // 默认宽度 (px)
  height: 800,                    // 默认高度 (px)
  minWidth: 800,                  // 最小宽度
  minHeight: 600,                 // 最小高度
  maxWidth: undefined,            // 最大宽度(不限制则留空)
  maxHeight: undefined,           // 最大高度(不限制则留空)
  resizable: true,                // 是否可调整大小
  fullscreenable: true,           // 是否允许全屏
  alwaysOnTop: false,             // 是否始终置顶
  frame: true,                    // 是否显示窗口边框(标题栏,关闭按钮)
  titleBarStyle: 'default',       // 标题栏样式:'default' | 'hidden' | 'hiddenInset'(仅 macOS)
  backgroundColor: '#5127ce',     // 加载时的背景色
  show: false,                    // 是否立即显示窗口(false 可等页面渲染后再显示,防白屏)
  webPreferences: {
    // 以下三项会被强制覆盖,配置无效(实际运行值以强制为准):
    nodeIntegration: false,       // 实际强制为 true
    contextIsolation: true,       // 实际强制为 false
    sandbox: false,               // 实际强制为 false

    // 其他 webPreferences 属性均可自由配置,例如:
    plugins: true,
    webSecurity: true,
    allowRunningInsecureContent: false,
    enableWebAuthn: true,
    // ... 更多 electron 支持选项
  },
}
  • 基础尺寸(width / height / minWidth / minHeight / maxWidth / maxHeight):窗口的初始尺寸与缩放范围; maxWidth / maxHeight 留空表示不限制;
  • 行为控制(resizable / fullscreenable / alwaysOnTop / frame):是否可缩放,是否允许全屏,是否置顶, 是否显示系统标题栏;
  • titleBarStyle:仅 macOS 生效;'default' 显示标准标题栏;'hidden' / 'hiddenInset' 隐藏标题栏(常用于自定义无边框 UI);
  • backgroundColor:窗口内容加载完成前显示的背景色,与 show: false 配合使用可避免白屏;
  • show:是否立即显示窗口;设为 false 时,Electron 会等页面渲染完成后再显示(推荐,防白屏);

webPreferences(重点)

webPreferences 中,以下三项会被本工具在创建窗口时强制覆盖,无论你在配置里怎么写:

配置项你的配置实际运行值原因
nodeIntegration任意true渲染进程需使用 Node.js API 以管理 Node.js 子进程
contextIsolation任意false渲染进程需直接访问 Electron 模块
sandbox任意false保证 Node.js 子进程能够正常启动

安全提示:以上三项强制覆盖意味着渲染进程拥有完整的 Node.js 能力,请确保你的应用只加载受信任的本地内容, 不要加载任何外部网页,否则存在严重安全风险;

除上述三项外,其余 webPreferences 选项均正常生效,可自由配置,例如 plugins,webSecurity, allowRunningInsecureContent,enableWebAuthn 等;

扩展说明:window 对象支持直接添加 electron-builder / Electron 官方支持的其他窗口字段(如 modal,parent, opacity 等),工具会原样传递给 Electron;


3. 菜单配置 (menu)

作用:定义应用顶部菜单栏的结构,语言与交互;采用 Electron 标准菜单模板,支持角色(role), 分隔符(type: 'separator')和自定义点击回调(click);

menu: [
  {
    label: '文件',
    submenu: [
      { role: 'close', label: '关闭' },
      { type: 'separator' },
      { role: 'quit', label: '退出' }
    ]
  },
  {
    label: '编辑',
    submenu: [
      { role: 'undo', label: '撤销' },
      { role: 'redo', label: '重做' },
      { type: 'separator' },
      { role: 'cut', label: '剪切' },
      { role: 'copy', label: '复制' },
      { role: 'paste', label: '粘贴' },
      { role: 'selectAll', label: '全选' }
    ]
  },
  // ... 更多菜单
]
  • role:使用 Electron 标准角色(如 undo,redo,cut,copy,paste,reload,toggleDevTools 等), 行为与快捷键自动绑定;
  • label:菜单项的显示文本,可自由改为任意语言;
  • type: 'separator':分隔线;
  • click:自定义回调,可写函数字符串(如 `() => { ... }`),工具会 eval 执行;
  • 特殊标记 '__TOGGLE_BROWSER__':出现在 click 位置时,会被替换为"在系统默认浏览器中打开 appUrl"的功能;

菜单内容完全自由,你可以增删菜单,改变语言,调整结构--它只是一个数组,交给 Electron 的 Menu.buildFromTemplate 使用;


4. 打包配置 (build)

作用:定义应用的打包输出,应用标识,图标,安装程序,签名等所有与最终产物相关的配置;build 对象会与 electron-builder 的原生配置合并,你可以直接添加任何 electron-builder 官方支持的字段(如 extraResources,publish,afterPack 等);

构建时自动优化 node_modules:本工具在 npm install 完成后、electron-builder 打包前, 先按需编译原生模块(nativeModules.npmRebuild: true 时),再自动执行 6 阶段优化,在物理层面清理依赖中的非运行文件, 构建产物更小,启动更快;

6 阶段优化流程:

  1. 清空复制到项目根的资源:扫描各包 postinstall 引用的目录/文件(如 templates/ / static/ / customize/),保留目录结构,清空内容(让包内 existsSync 自检通过);js 文件一律保留,留待合并阶段处理;
  2. 合并 JS:按包入口 bundle,多个 JS 文件合并为单文件(bundled/index.mjs / index.cjs);CJS 保持 CJS,ESM 保持 ESM; 合并后删除各包 package.json 的 scripts 字段(运行时无安装期,编译已在优化前完成,安装期脚本无用);
  3. 清平台二进制:逐文件判定,删除非当前平台 / 架构的二进制.采用三层识别(目录名含平台词 → 系统专有后缀 → 文件头魔数), 并在平台相同时进一步比对架构(从 PE / ELF / Mach-O 文件头解析 x64 / arm64 等);目录名可任意改,后缀可缺,仍能靠文件内容判定; 同时清理 @scope/平台纯二进制包;
  4. 清开发文件:删除 .md / .map / .yml / .h / .c / .gyp / tsconfig.json / .nycrc / .editorconfig / package-lock.json 等非运行文件;递归进入嵌套 node_modules,清理多层依赖中的同类文件;原生模块编译已在优化前完成, 编译类文件一律清理,仅保留 .node;
  5. 清中间产物:删除 package.json.orig 等合并临时文件,以及 node-gyp 编译中间产物(.vcxproj / .tlog / .iobj / .ipdb / .exp / .lib / .obj / .recipe / .lastbuildstate / .pdb / .nativecodeanalysis.xml);
  6. 清不参与运行的文件和空目录:删除以下非运行文件,并自底向上清除空目录:
    • license* / licence* / LICENSE* / LICENCE*(含 LICENSE-MIT 等变体)
    • .ts / .cts / .mts
    • 顶层 node 假包
    • node-win* / node-darwin* / node-linux* 等平台假包

构建判断与执行:每次构建自动判断并执行三种动作之一,日志会说明当次动作与原因:

  • 三种动作的触发条件见上文的"构建时自动判断并执行三种动作";

判断依据记录在临时目录的 .deps-snapshot.json 中;构建失败时状态被清除,下次自动重装重优化;

日志:默认精简(安装,优化汇总,打包,成功);加 --debug 可显示优化各阶段明细与 electron-builder 完整输出,详见 9. 调试构建;

优化的开关与逃生舱口:

  • optimize: { enabled: false }:整体关闭优化;
  • optimize: { exclude: ['包名'] }:排除优化时异常或不想优化的包;
  • 若需额外排除项目文件,仍使用 excludeFiles(作用于复制阶段,与优化系统独立);

electron-builder 的 files 数组仅排除工具自身生成的 builder.json 与用户的 excludeFiles;node_modules 内部的清理完全交由优化系统处理.因此若设置 optimize: { enabled: false },node_modules 将保持原始内容(体积较大)--这是关闭优化换取"完全不动依赖"的代价;

关于 asar:本工具默认禁用 asar 打包;原因详见 简介中的说明;因此 resources/app 始终是真实目录结构, Node.js 子进程能正常读取文件;

4.1 通用字段

作用:与平台无关的打包基础配置;

build: {
  appId: 'com.example.app',           // 应用唯一标识(反向域名格式)
  outputDir: './dist',                // 安装包输出目录
  publisher: null,                    // 发布者名称(默认从 package.json 读取 author)
  shortcutName: null,                 // 快捷方式名称(默认使用 appName)
  nativeModules: {
    npmRebuild: false,                // 不重编译原生模块,减少构建时间
  },
  // ... 其他 electron-builder 字段可自由添加
}
  • appId:应用唯一标识,采用反向域名格式(如 com.mycompany.myapp),用于注册表,应用识别,升级判断;
  • outputDir:最终安装包的输出目录,默认为 ./dist;
  • publisher:发布者名称,用于安装程序信息;不填则从 package.json 的 author 读取;
  • shortcutName:快捷方式显示名称;不填则使用 appName;
  • nativeModules.npmRebuild:是否编译原生模块(默认 false);设为 true 时,在依赖安装后,node_modules 优化前先执行 electron-rebuild 编译原生模块,优化阶段随即可清理全部编译文件与中间产物,产物只保留 .node;设为 false 则跳过编译, 使用包自带的预编译二进制,构建更快;
  • toolsets:electron-builder 的官方字段,会被原样写入 builder.json;但本工具只构建当前运行平台,toolsets 不会改变构建结果--它只在与 electron-builder 的跨平台构建能力配合时才有意义;本工具不提供跨平台构建入口, 因此不建议配置此字段;若你仍写入,构建不会被阻断,但也不会有任何效果;

4.2 Windows (build.win)

作用:Windows 平台的应用配置;

build: {
  win: {
    icon: './build/icon.png',         // 应用图标(建议 512×512 PNG)
    // sign: { ... }                  // 应用本体签名 → 详见"代码签名"章节
    // ... 其他 electron-builder 的 win 字段可自由添加
  },
}
  • icon:应用图标,建议 512×512 PNG,用于快捷方式和可执行文件图标;
  • sign:应用本体签名配置,作用于打包后的应用可执行文件(如 deskApp.exe)及所有附带 .exe 程序;详细配置与操作请见 代码签名 → 一,Windows 应用本体签名;

扩展说明:build.win 支持直接添加任何 electron-builder 官方支持的 Windows 字段(如 publisherName, requestedExecutionLevel,target 等);

4.3 Inno Setup (build.inno)

作用:配置 Windows 安装程序(基于 Inno Setup);涵盖安装界面,图标图片,权限,压缩,快捷方式, 安装后运行等;用户只需配置常用字段,工具会自动生成符合 Inno Setup 7.x 规范的 .iss 脚本;

通用字段(常用):

build: {
  inno: {
    // ---- 基础信息 ----
    appName: undefined,               // 应用显示名称(默认使用 appName)
    appVersion: undefined,            // 版本号(默认从 package.json 读取 version)
    appPublisher: undefined,          // 发布者(默认使用 build.publisher 或 package.json author)
    appId: undefined,                 // 应用唯一标识(默认使用 build.appId)
    defaultDirName: null,             // 默认安装目录(如 '{autopf}\\MyApp')
    defaultGroupName: undefined,      // 开始菜单文件夹名(默认 appName)
    outputDir: undefined,             // 输出目录(默认使用 build.outputDir)
    outputBaseFilename: undefined,    // 安装包文件名(默认 `${appName}Setup`)

    // ---- 界面控制 ----
    disableWelcomePage: false,        // 跳过欢迎页
    disableDirPage: false,            // 禁止更改安装路径
    disableProgramGroupPage: false,   // 禁止选择开始菜单文件夹
    disableFinishedPage: false,       // 隐藏"安装完成"页面
    disableReadyPage: false,          // 隐藏"准备安装"确认页
    disableReadyMemo: false,          // 准备页不显示设置摘要
    disableStartupPrompt: false,      // 禁止启动时显示"是否安装..."提示
    showLanguageDialog: true,         // 显示语言选择对话框
    flatComponentsList: false,        // 组件列表使用扁平样式
    showComponentSizes: false,        // 显示每个组件大小
    showTasksTreeLines: false,        // 任务页显示树形连线

    // ---- 图标与图片 ----
    setupIconFile: './build/setup.ico',                       // 安装程序图标(.ico)
    uninstallDisplayIcon: './build/uninstallerIcon.ico',      // 卸载程序图标(.ico)
    WizardImageFile: './build/wizard.bmp',                    // 左侧大图(164×314 BMP)
    WizardSmallImageFile: './build/wizardSmall.bmp',          // 右上小图(55×58 BMP)
    WizardImageFileDynamicDark: './build/wizard.bmp',         // 深色模式左侧大图
    WizardSmallImageFileDynamicDark: './build/wizardSmall.bmp',// 深色模式右上小图

    // ---- 向导样式与颜色 ----
    WizardStyle: 'dynamic',           // modern / classic / dynamic / dark / light...
    WizardImageBackColor: '#CE2751',  // 标准模式左侧大图背景色
    WizardSmallImageBackColor: '#CE2751', // 标准模式右上小图背景色
    WizardBackColor: '#CE2751',       // 标准模式背景色
    WizardImageBackColorDynamicDark: '#228866',      // 深色模式左侧大图背景色
    WizardSmallImageBackColorDynamicDark: '#228866', // 深色模式右上小图背景色
    WizardBackColorDynamicDark: '#228866',           // 深色模式背景色
    WizardImageStretch: true,         // 向导图片是否填充整个区域

    // ---- 权限 ----
    privilegesRequired: 'lowest',     // admin / lowest / poweruser
    privilegesRequiredOverridesAllowed: 'dialog', // 允许通过对话框提升权限

    // ---- 压缩 ----
    compression: 'lzma2',             // lzma2 / zip / none
    solidCompression: true,           // 固实压缩
    LZMADictionarySize: 4096,         // LZMA 字典大小(KB)
    LZMANumFastBytes: 64,             // LZMA 快速字节数

    // ---- 快捷方式 ----
    createDesktopShortcut: true,      // 创建桌面快捷方式
    createStartMenuShortcut: true,    // 创建开始菜单快捷方式
    shortcutName: undefined,          // 快捷方式名称(默认使用 build.shortcutName)

    // ---- 安装后运行 ----
    runAfterInstall: true,            // 安装完成后是否运行应用
    runDescription: '运行应用',        // 运行复选框的描述文字

    // ---- 高级选项 ----
    languageDetectionMethod: 'uilanguage', // uilanguage / locale / none
    allowCancelDuringInstall: true,   // 允许安装过程中取消
    usePreviousAppDir: true,          // 记住上次安装目录(清除用户数据时一并清除)
    usePreviousGroup: true,           // 升级时记住开始菜单文件夹
    usePreviousSetupType: true,       // 升级时记住安装类型
    usePreviousTasks: true,           // 升级时记住任务选择
    usePreviousLanguage: true,        // 升级时记住语言选择
    uninstallable: true,              // 是否可卸载
    createUninstallRegKey: true,      // 创建卸载注册表项
    uninstallDisplayName: '卸载(应用名)', // "添加/删除程序"中显示的名称
    uninstallLogMode: 'append',       // 卸载日志模式:new / append / overwrite

    // ---- 版本信息 ----
    versionInfoVersion: undefined,    // 文件版本(默认使用 inno.appVersion)
    versionInfoDescription: undefined,// 文件描述
    versionInfoCopyright: undefined,  // 版权信息
    versionInfoCompany: undefined,    // 公司名称(默认从 package.json 读取 author)

    // ---- 系统要求 ----
    minVersion: '10.0.17763',         // 最低 Windows 版本(默认 Win10 1809+)
    onlyBelowVersion: '',             // 限制最高可运行版本
    useSetupLdr: true,                // 使用 SetupLdr 引导程序(处理 UAC 和系统版本检查)

    // ---- 签名 ----
    // signedUninstaller: false,      // 是否为卸载程序签名
    // signingTool: undefined,        // 签名工具 → 详见"代码签名"
    // signToolParams: undefined,     // 签名参数(对象格式) → 详见"代码签名"

    // ... 其他 Inno Setup [Setup] 节指令可直接添加
  },
}
  • 基础信息:appName / appVersion / appPublisher / appId 均会自动从其他配置继承,通常无需手动填写;
  • 界面控制:通过 disable* 系列字段控制向导页的显示与否,你可以按需精简安装流程;
  • 图标与图片:所有图片资源均为可选,不配置则使用默认或省略;所有硬编码路径(如 ./build/xxx)都会在项目根目录下解析;
  • 向导样式:WizardStyle: 'dynamic' 支持自动切换深浅色,与系统主题同步;
  • 权限:privilegesRequired: 'lowest' 表示最低权限(无需管理员),'admin' 表示需要管理员;
  • 压缩:lzma2 压缩率最高,zip 兼容性最好,none 不压缩;
  • 签名:signingTool 与 signToolParams 必须同时配置才会启用签名, 且需符合对象格式;详细配置见 代码签名;

扩展说明:build.inno 支持直接添加任何 Inno Setup 官方支持的 [Setup] 节指令(按 Inno Setup 规范书写即可); 完整指令列表参考 Inno Setup 官方文档;

安装任务:安装向导的"选择附加任务"页提供一个复选框:

  • 将应用加入 Windows Defender 排除项,加快启动(默认勾选)--应用每次启动会被 Defender 实时扫描安装目录下的大量文件(node_modules 内成千上万小文件),拖慢冷启动;勾选后将安装目录加入排除项,不再被扫描, 冷启动明显加快;
    • 如不需要,可在安装时取消勾选;代价是每次开机首次启动会被扫描,稍慢;
    • 仅 Windows 生效;第三方杀毒软件(360 / 火绒 / 卡巴斯基等)机制各异,本功能不处理;

卸载行为:除 Inno Setup 标准卸载流程外,本工具生成的卸载程序还会自动执行以下清理(无需用户配置):

  • 终止应用进程:卸载开始时自动结束运行中的应用及其 Node.js 子进程,避免文件被占用导致清理不净;
  • 删除防火墙规则:应用运行时会触发 Windows 自动创建的同名入站防火墙规则;卸载时一并删除,避免多次安装后规则累积残留;
  • 清空安装目录:卸载完成后清除整个安装目录(含非安装清单内的文件,如应用运行期间产生的会话数据);
  • 用户数据与安装目录记忆:卸载时弹窗询问是否删除用户数据(%APPDATA%\<appName>);选择删除时, 同时清除安装目录记忆(usePreviousAppDir)--下次安装回到默认位置;选择保留则记忆保留,下次安装仍默认使用原路径.
  • 移除 Defender 排除项:若安装时加入了 Windows Defender 排除项, 卸载时选择删除用户数据则一并移除(避免指向已删除目录的排除项残留);选择保留则保留(仅 Windows).

4.4 macOS 与 DMG (build.mac / build.dmg)

作用:build.mac 配置 macOS 应用的打包目标与签名;build.dmg 配置 DMG 卷宗的外观与布局;仅在 macOS 上构建时生效;

build: {
  mac: {
    target: ['zip', 'dmg'],          // 构建目标:dmg / zip / pkg / mas 等
    // icon: './build/icon.icns',    // 应用图标(.icns,需自备)
    // sign: { ... }                 // 签名配置(公证开关在 mac.notarize)→ 详见"代码签名"章节
    // ... 其他 electron-builder 的 mac 字段可自由添加
  },
  dmg: {
    iconSize: 80,                            // 图标大小
    window: { width: 540, height: 380 },     // DMG 窗口尺寸
    // background: './build/background.png', // 背景图片(建议 PNG,540×380)
    // backgroundColor: '#5127ce',           // 无背景图时的背景色
    // icon: './build/icon.icns',            // DMG 卷宗图标
    // title: '${productName} ${version}',   // 挂载后显示的卷宗名称
    // format: 'UDZO',                       // 压缩格式(UDZO/ULFO/UDBZ 等)
    // contents: [                           // 自定义图标布局
    //   { x: 130, y: 220, type: 'file' },
    //   { x: 410, y: 220, type: 'link', path: '/Applications' }
    // ]
  },
}
  • mac.target:构建目标格式;dmg 为磁盘映像,zip 常用于自动更新,pkg 为安装包,mas 为 Mac App Store 专用;
  • mac.icon:.icns 格式图标,需自备(工具包内仅提供跨平台 PNG,不含 .icns);
  • mac.sign:macOS 签名配置;公证开关在 mac.notarize(boolean); 详细配置与操作请见 代码签名 → 三,macOS 签名与公证 (mac.notarize);
  • dmg.*:DMG 卷宗外观,全部为可选增强项,不配置则使用默认样式;

扩展说明:build.mac 与 build.dmg 支持直接添加 electron-builder 官方支持的任何 macOS / DMG 字段;

4.5 Linux (build.linux)

作用:配置 Linux 平台的应用打包目标与元信息;仅在 Linux 上构建时生效;

build: {
  linux: {
    target: ['AppImage', 'deb'],     // 构建目标:AppImage / deb / rpm / snap / flatpak 等
    category: 'Development',         // 系统菜单分类
    // description: '完整的应用描述',
    // synopsis: '简短描述',
    // maintainer: '你的名字 <[email protected]>',
    // vendor: '我的公司',
    // executableArgs: ['--enable-features=...'],
    // desktop: { entry: { Name: '我的应用', Comment: '...', ... } }, // 自定义 .desktop 文件
    // sign: { ... }                 // GPG 签名(本工具便利字段,构建时剥离并转环境变量)→ 详见"代码签名"章节
    // ... 其他 electron-builder 的 linux 字段可自由添加
  },
}
  • linux.target:可同时指定多种格式,构建时会生成多个安装包;
  • category:系统菜单中的分类,如 Utility / Network / Development;
  • Linux 图标:无需显式配置,只需在 ./build 目录下提供 icon.png(建议 512×512 PNG),工具会自动识别;
  • linux.sign:本工具提供的便利字段(非 electron-builder 官方字段),用于配置 Linux 包的 GPG 签名, 构建时会自动剥离并转换为环境变量;详细配置与操作请见 代码签名 → 四,Linux 包签名;

扩展说明:build.linux 支持直接添加 electron-builder 官方支持的任何 Linux 字段;


5. 高级选项 (advanced)

作用:控制应用与 Node.js 子进程的启停关系;

advanced: {
  autoStartServer: true,   // 应用启动时自动运行 Node.js 子进程
  autoKillServer: true,    // 应用退出时自动关闭 Node.js 子进程
}
  • autoStartServer:设为 true 时,Electron 主窗口加载前会自动启动 serverPath 指定的 Node.js 子进程, 等待其就绪后再显示窗口;就绪探测动态跟随 appUrl 的主机与端口,appUrl 填固定地址(127.0.0.1,::1)或动态地址(域名, 具体绑定主机)均兼容,探测目标始终与窗口加载地址一致,避免服务器已监听却因探测回环而误判未就绪;默认 true;
  • autoKillServer:设为 true 时,应用退出时会自动关闭 Node.js 子进程,避免残留;默认 true;

6. 允许安装脚本 (allowScripts)

作用:构建阶段安装生产依赖时,放行指定包名的 npm 安装脚本(如 postinstall);用于解决 npm 全局配置中 ignore-scripts=true 导致某些包安装不完整的问题;

allowScripts: {
  'node': true,
  '@flun/webauthn-server': true,
}
  • 键为 npm 包名,值为 true 表示允许执行该包的安装脚本;
  • 未配置或配置错误时,工具会警告并使用默认值 { node: true };
  • 仅在构建阶段 npm install --production 时生效,与 package.json 中的 allowScripts(npm 安装本项目时使用)场景不同;

说明:如果你在项目 .npmrc 中设置了 ignore-scripts=true,则应在此配置里显式放行必需的包;


7. 排除规则

7.1 excludeFiles

作用:复制项目文件到临时构建目录时,排除指定的文件/目录(支持 glob 模式); 这些模式会自动转换为 electron-builder 的排除规则(前缀 !),因此也会在打包阶段生效;

excludeFiles: [
  '.vscode/',
  '.git/',
  'dist/',
  '*.log',
  './yarn.lock',
]

匹配规则:

  • 以 / 结尾:匹配该目录及其全部内容(如 '.git/');
  • 以 ./ 开头:仅匹配项目根目录下的文件(非递归,如 './yarn.lock');
  • 其他:按 minimatch 全局匹配(如 '*.log' 匹配任意路径下所有 .log 文件);

注意:依赖已被工具主动处理(构建时安装),因此不建议排除 node_modules;

7.2 excludeDependencies

作用:从最终安装的依赖列表中移除指定的 npm 包(这些包不会被打包到应用中);

excludeDependencies: [
  '@flun/desktop-builder',   // 构建工具自身
  '@flun/windows',            // 用不到的平台专用包
]
  • 常用于排除构建工具自身的依赖或已确认无用的包;
  • 排除后的包不会出现在最终的 node_modules 中;

7.3 excludeOutputs

作用:将构建好的安装包从临时目录复制到最终输出目录时,排除特定文件;

excludeOutputs: [
  '*.blockmap',
  'latest.yml',
]
  • 常用于排除自动更新相关文件(如 *.blockmap,latest.yml)--若你不需要自动更新,可去掉它们;
  • 仅影响复制到输出目录的阶段,不影响 electron-builder 的构建过程;

8. node_modules 优化 (optimize)

作用:控制构建时的 node_modules 优化系统(默认开启);六阶段流程详见 4. 打包配置;

export default {
  // 默认开启,无需配置

  // ===== 关闭优化(构建或运行异常时使用)=====
  // optimize: { enabled: false },

  // ===== 排除优化时异常或不想优化的包(默认空)=====
  // optimize: { exclude: ['包名'] },
};
  • 不配置:优化系统默认开启;构建时自动执行六阶段优化,大幅减少打包文件数和体积,加速冷启动;
  • optimize: { enabled: false }:整体关闭优化;用于排查"是否优化系统引起的异常"--若关闭后问题消失, 说明是优化系统的某些清理动作引起的;
  • optimize: { exclude: ['包名'] }:排除优化时异常或不想优化的包--只跳过该包的优化,其余包继续享受优化;包名写 package.json 中的 name 字段值(如 qrcode,@flun/html-template);
  • 调试步骤:
    1. 运行 npx desktop-builder build --debug 查看详细日志(优化各阶段明细,electron-builder 完整输出),初步定位问题;
    2. 遇到异常,先 optimize: { enabled: false } 快速判断是否为优化引起;
    3. 确认后,用 optimize: { exclude: ['问题包名'] } 逐个定位并排除;
    4. 若需完全重来,删除临时目录 %TEMP%\desktop-builder-build(Windows)后重新构建;

提示:优化系统只处理 node_modules,不触碰你的项目源码和资源文件;若需排除项目里的文件/目录,请使用 excludeFiles;

9. 调试构建 (--debug)

作用:--debug 是命令行开关,显示构建过程的详细日志,用于排查问题;

npx desktop-builder build --debug

开启后额外显示:

  • 优化各阶段明细:阶段 1 被清空的资源目录及文件,阶段 2 每个包的合并入口,阶段 3 每个被删除的二进制及原因(平台不符 / 架构不符);
  • electron-builder 完整输出:默认模式下这些输出被隐藏(仅构建失败时打印,便于排查),--debug 下实时显示;

默认行为:不加 --debug 时,构建日志保持精简--仅显示关键进度(安装,优化各阶段汇总,打包,成功);优化明细与 electron-builder 输出被隐藏,构建失败时自动打印后者;

代码签名

本工具已内置跨平台签名适配,用户只需填写最少的字段,其余转义,拼接,查找,校验均由构建脚本自动完成;

一,Windows 应用本体签名 (build.win.sign)

electron-builder v27 要求 win.sign 必须带 type 判别字段,取消模板中的注释后按实际填写:

build: {
  win: {
    icon: './build/icon.png',
    sign: {
      type: 'signtool',                                     // 必填,固定为 'signtool'
      certificateFile: './build/cert.pfx',                  // 证书文件路径(.pfx)
      certificatePassword: process.env.CSC_KEY_PASSWORD,    // 证书密码(推荐用环境变量)
      signingHashAlgorithms: ['sha256'],
    },
  },
}
  • 环境变量 CSC_KEY_PASSWORD 需在构建前设置;
  • 该签名作用于打包后的应用可执行文件(如 deskApp.exe)及所有 .exe 附带程序(如 lego.exe);
  • 不填 win.sign 时跳过签名,构建仍正常完成;

配置严格校验(构建前):

为避免用户等几分钟打包完才发现配置错误,本工具在构建开始前(复制文件之前)即校验 win.sign, 任何问题都会在 1 秒内报错退出:

  • type 必填,缺失时报 [错误] build.win.sign.type 必填(...);
  • certificateFile 与 identity 至少配置一个,缺失时报 [错误] 请配置 build.win.sign 中的 certificateFile 或 identity 字段;
  • certificateFile 指向的文件必须存在,否则报 [错误] 证书文件不存在: <绝对路径>;

二,Windows 安装程序与卸载程序签名 (build.inno)

build.inno 下三个字段只需填最基本的 3 项即可:

build: {
  inno: {
    signedUninstaller: true,               // 是否同时为卸载程序 unins000.exe 签名
    signingTool: 'signtool.exe',           // 签名工具:可填短名(自动查找)或完整路径
    signToolParams: {                      // 对象格式,仅需 3 项
      certificateFile: './build/cert.pfx',
      certificatePassword: 'your-password',
      algorithm: 'sha256',                 // 默认 sha256
    },
  },
}

自动兜底机制:

  1. signingTool 自动查找:填 'signtool.exe' 时,构建脚本会按以下顺序查找完整路径:
    • 若填的是工具路径(相对或绝对均可) → 直接验证存在性;
    • 否则调用 where signtool.exe 查 PATH;
    • 再依次扫描 %ProgramFiles(x86)%\Windows Kits\10\bin\<版本>\<arch>\signtool.exe(x64 / x86 / arm64,版本从高到低);
    • 全部失败时给出中文提示并终止,不会静默使用错误的工具;
  2. signToolParams 对象自动拼接:build.js 会自动拼成 sign /f "证书" /p "密码" /fd 算法 $f,并自动完成 Inno Setup 所需的 $q 引号转义,用户无需关心任何转义字符;
  3. 合法性校验:
    • certificateFile 必填,且文件必须存在;
    • signingTool 只需填写工具名(如 signtool.exe,自动查找)或工具路径(相对或绝对均可),首尾空格会被自动忽略;
  4. SignTool 指令生成:脚本自动将工具名写入 .iss 的 [Setup] 段,并通过 /S<name>=... 命令行参数向 ISCC 传入完整命令,符合 Inno Setup 官方规范;

配置严格校验(构建前):

与 win.sign 一样,inno 签名配置也在构建开始前完成校验,任何问题 1 秒内报错退出:

  • signingTool 与 signToolParams 必须同时配置:只配其一时报 [错误] build.inno 的 signingTool 与 signToolParams 必须同时配置,并提示缺哪个;
  • signingTool 解析失败时报 [错误] 找不到签名工具: <名称>;
  • signToolParams.certificateFile 必填,缺失时报 [错误] signToolParams.certificateFile 必填;
  • certificateFile 指向的文件必须存在,否则报 [错误] 证书文件不存在: <绝对路径>;

三,macOS 签名与公证 (mac.notarize)

按照 electron-builder v27 官方规范:签名选项位于 mac.sign 下,公证开关位于 mac.notarize 下(boolean 类型,不是对象);

build: {
  mac: {
    notarize: false,                         // boolean;false 显式关闭;true 时本工具构建前检查凭据;
                                             // 不配置则透传给 electron-builder
    sign: {
      identity: 'Developer ID Application: Your Name (TEAM123)',  // 签名身份(名称或 SHA-1)
      hardenedRuntime: true,                 // 公证必需(darwin 构建默认 true)
      entitlements: './build/entitlements.mac.plist',
      entitlementsInherit: './build/entitlements.mac.inherit.plist',
      // ... 其他 ElectronSignOptions 字段(timestamp,requirements 等)
    },
  },
}

公证凭据必须通过环境变量传入(不能写在配置里),以下三种方式任选其一:

方式环境变量
Apple IDAPPLE_ID,APPLE_APP_SPECIFIC_PASSWORD,APPLE_TEAM_ID
API Key(CI 推荐)APPLE_API_KEY,APPLE_API_KEY_ID,APPLE_API_ISSUER
Keychain ProfileAPPLE_KEYCHAIN,APPLE_KEYCHAIN_PROFILE

证书文件与密码也必须通过环境变量传入(mac.sign 无 certificateFile / certificatePassword 字段):

环境变量说明
CSC_LINK证书文件路径(.p12)或 base64 内容
CSC_KEY_PASSWORD证书密码

兼容说明:本工具额外接受以下旧写法作为便利字段,构建时会自动剥离这些非官方字段,不会触发 electron-builder 的 additionalProperties: false 校验:

  • sign.certificateFile / sign.certificatePassword → 转换为 CSC_LINK / CSC_KEY_PASSWORD 环境变量;
  • sign.notarize(旧的对象写法)→ 直接丢弃;如需启用公证,请设置 mac.notarize: true,并通过环境变量提供凭据(见上表);

仍推荐按上述 v27 官方规范书写;

配置严格校验(构建前):

与 Windows 一致,以下情形会在构建开始前报错退出(复制文件之前),不进入打包流程:

  • notarize 必须为 boolean(true / false),写成对象会报错;
  • notarize: true 时,本工具会在构建前检查公证凭据(环境变量)是否完整;若只配置部分(例如只设了 APPLE_ID,缺 APPLE_APP_SPECIFIC_PASSWORD 或 APPLE_TEAM_ID),会报错并提示缺哪些;

关于不配置 notarize:本工具只在你显式设置 notarize: true 时检查凭据;false 时不做任何处理;若完全不配置该字段, 行为完全交由 electron-builder 决定,请以其官方文档为准;如不需要公证,建议显式设置 notarize: false;

四,Linux 包签名

electron-builder 本身不签名 Linux 包,实际签名依赖底层工具:deb 通过 dpkg-sig,AppImage 通过 appimagetool --sign, 均基于 GPG 密钥;

v27 的 linux 配置下没有 sign 字段;GPG 签名通过环境变量触发:

GPG_PRIVATE_KEY=<ASCII-armored 私钥内容>
GPG_KEY_PASSPHRASE=<密钥密码>

设置上述环境变量后,构建 Linux 包时会自动签名;使用前请确保宿主机已安装 dpkg-sig,appimagetool 及对应的 GPG 密钥;

兼容说明:本工具额外接受 build.linux.sign.gpgPrivateKey / build.linux.sign.gpgKeyPassphrase(旧写法)作为便利字段, 构建时会自动剥离 sign 字段并转换为上述环境变量,不会触发 electron-builder 的 additionalProperties: false 校验; 仍推荐直接使用环境变量;

配置严格校验(构建前):

与 Windows 一致,linux.sign 的 gpgPrivateKey 与 gpgKeyPassphrase 必须同时配置, 只配其一会在构建开始前报错退出(复制文件之前),并提示缺哪个,避免走到打包后期才失败;


五,生成并信任自签名测试证书

(一)生成证书

正式发布请使用受信任 CA 签发的代码签名证书;若只是想本地验证签名流程,可用 PowerShell 生成一张自签名的代码签名证书:

$pwd = ConvertTo-SecureString -String "证书密码" -Force -AsPlainText
$cert = New-SelfSignedCertificate `
  -Type CodeSigningCert `
  -Subject "CN=Test Code Signing" `
  -CertStoreLocation Cert:\CurrentUser\My `
  -NotAfter (Get-Date).AddYears(1)
Export-PfxCertificate -Cert $cert -FilePath "证书文件路径" -Password $pwd
  • -Type CodeSigningCert 必须带,否则证书 EKU 不含 Code Signing,signtool 会直接过滤掉;
  • 生成的 .pfx 可配合 build.win.sign 与 build.inno.signToolParams 使用;
  • 自签名证书默认不被系统信任:signtool verify 时会提示 A certificate chain processed, but terminated in a root; 可按下方(二)把证书公钥导入目标机器的受信任根;导入后该机器即完全信任,不再报警;

(二)让目标机器信任证书 自签名证书要生效,需将其公钥部分(不含私钥)导入系统的"受信任根证书颁发机构"; 切勿将带私钥的 .pfx 导入受信任根--那等同于公开签名权;

第一步:导出公钥(.cer 文件,不含私钥)

$pfx = "证书文件路径"
$cer = "公钥输出路径"

$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($pfx, "证书密码")
$pubBytes = $cert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert)
[System.IO.File]::WriteAllBytes($cer, $pubBytes)

第二步:把 .cer 导入受信任根--三种方式任选:

方式一:双击导入(图形界面,最简单)

  • Windows:双击 .cer → "安装证书"→ 选择"本地计算机"(需管理员)或"当前用户"→ "将所有的证书都放入下列存储"→ 选择"受信任的根证书颁发机构"→ 完成;若弹出安全警告,点"是";
  • macOS:双击 .cer → 自动打开"钥匙串访问"→ 将证书拖入"系统"或"登录"钥匙串 → 双击该证书 → 展开"信任"→ 将"使用此证书时"设为"始终信任"→ 关闭窗口时输入系统密码保存;
  • Linux(桌面发行版):将 .cer 复制到 /usr/local/share/ca-certificates/(文件后缀改为 .crt),然后执行 sudo update-ca-certificates;

方式二:命令行导入(可脚本化)

  • Windows(管理员 PowerShell / CMD):

    certutil -addstore Root "证书公钥.cer"
    

    (加 -user 参数则导入"当前用户"而非"本地计算机")

  • macOS:

    sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain "证书公钥.cer"
    
  • Linux(Debian / Ubuntu):

    sudo cp "证书公钥.cer" /usr/local/share/ca-certificates/自定名.crt
    sudo update-ca-certificates
    

    (CentOS / RHEL 使用 sudo cp ... /etc/pki/ca-trust/source/anchors/ 后执行 sudo update-ca-trust)

方式三:企业内网批量分发

  • Windows 域环境:通过组策略(GPO)推送证书到所有域机器的"受信任根证书颁发机构";
  • macOS:通过 MDM(如 Jamf,Munki)或配置描述文件下发;
  • Linux:通过 Ansible,Puppet 等自动化工具批量部署;

适用场景(以下均可让目标机器信任自签名证书):

  • 个人多台设备:自己开发者的 PC,笔记本,虚拟机等,每台各导入一次;
  • 团队协作:团队成员把公钥导入各自电脑,团队成员间共享可信任的安装包;
  • 公司内网:IT 部门通过组策略 / MDM / 自动化工具,把公钥分发到内网所有机器;
  • CI/CD 构建机:构建服务器导入公钥后,产出的安装包在部署环境(若也导入了同一公钥)里不再报警;
  • 测试环境:QA,预发布机器导入后,测试安装流程无需手动跳过警告;
  • 虚拟机模板 / 镜像:把公钥打进系统镜像,新开的虚拟机天然信任;

不适用场景(以下必须使用受信任 CA 签发的证书):

  • 公开发布给陌生用户:下载方未导入你的公钥,仍会提示"未知发布者",Windows SmartScreen 也会拦截;
  • 上架应用商店:各商店要求使用受信任 CA 或平台专属证书;
  • 企业对外分发:客户/合作伙伴无法接受"手动导入你的公钥"这种前置步骤;

公开分发请购买受信任 CA 签发的代码签名证书(OV 或 EV);


关于网络依赖与构建性能

默认行为:构建时打包依赖

  • 构建时会自动执行 npm install --production,将 node_modules 完整打包进应用;
  • 用户首次启动无需联网,开箱即用;
  • 安装包体积会增大,构建和安装时间会增长(包含依赖),但这是换取流畅用户体验的代价;
  • 构建流程为"安装依赖 → 编译原生模块(nativeModules.npmRebuild: true 时)→ node_modules 优化 → 打包"; 优化系统(详见 8. node_modules 优化)按入口合并 JS,清理平台二进制与编译产物, 进一步减小体积,加速冷启动;用户无需任何操作;

如何回退到运行时安装依赖(旧行为)

若希望减小安装包体积,缩短构建时间,并允许用户首次启动时联网安装依赖,可安装 v2.1.7 及以下版本(不推荐);

注意:工具默认行为始终为"构建时打包依赖";强行排除 node_modules 会导致应用无法启动, 因为 Electron 需要依赖来运行 Node.js 项目;请保持默认行为;

优化建议

  • 无需任何操作:node_modules 优化系统默认开启,自动完成 JS 合并,平台二进制清理,开发文件清理等, 是本工具内置的最强优化手段;
  • 使用 excludeDependencies 自定义排除不需要打包进应用的依赖包(出于安全或减小体积等考虑);
  • 利用 build.compression: 'maximum' 压缩安装包(仅对 electron-builder 产物有效,Inno Setup 有自己的压缩设置);
  • Electron 缓存复用:构建时自动检查 Electron 缓存--已有当前版本的解压产物则直接复用,否则从 zip 解压(zip 也缺时由 electron-builder 下载);同时自动清理非当前版本的缓存,避免无限累积;

进一步定制

如果现有配置仍不能满足您的特殊需求,您可以通过以下方式进一步扩展:

1. 直接使用 electron-builder 配置字段

build 对象中允许添加任何 electron-builder 官方支持的配置(如 compression,extraResources,publish,afterPack 等), 它们会被正确合并到 builder.json 中;

2. 使用钩子脚本

通过设置 build.afterPack 或 build.afterAllArtifactBuild 等字段(指向项目中的脚本文件), 可以在构建过程中执行自定义操作(例如复制额外文件,重新签名,上传到服务器);

钩子路径说明:路径可填相对路径(相对项目根目录)或绝对路径,两种写法均受支持;构建时, 本工具会自动将钩子文件复制到临时构建目录,并将其路径改写为临时目录内的绝对路径--这是因为底层 electron-builder 要求钩子模块必须位于其 --project 指定的工作区(即本工具的临时目录)内,直接填写项目根目录下的路径会被 electron-builder 拒绝(报 Hook module path ... resolves outside the workspace root);用户无需关心这一细节,按正常相对/绝对路径填写即可;

3. 修改主进程模板(高级)

目前主进程由内置的 electron-main.js 模板生成;如需深度修改主进程逻辑,您可以使用 patch-package 对 @flun/desktop-builder 打补丁,或者 fork 项目并修改 build.js 以支持自定义模板路径(未来版本可能原生支持);

4. 自行调用 electron-builder

您也可以在 package.json 中编写自己的构建脚本,直接调用 electron-builder 并引用 @flun/desktop-builder 提供的临时构建目录,但这需要您自行管理复制,依赖安装等步骤;

推荐路径:优先尝试前两种(配置字段/钩子),如果仍不够,可向项目作者提交 Issue 或 PR 提出新增配置需求;


常见问题

1. 构建时提示 desktopAppConfig.js not found

  • 确认包已正确安装,postinstall 会自动复制模板;若未自动复制,可手动从 node_modules/@flun/desktop-builder/desktopAppConfig.js 复制到项目根目录;

2. 构建失败,提示 electron-builder 相关错误

  • 打包失败时本工具会自动打印 electron-builder 的完整输出,先看输出定位原因;
  • 若输出显示依赖缺失,工具会精确报出缺失的包名并提示"再次运行构建命令即可自动重装修复"--直接再跑一次即可;
  • 需要更详细的日志(如优化各阶段删了哪些文件)时,加 --debug 参数,详见 9. 调试构建;
  • 确保网络畅通,首次构建需下载 Electron 运行时(约 100MB);
  • 可尝试设置镜像环境变量(构建脚本已自动配置中国镜像,如 ELECTRON_MIRROR);

3. 应用版本号如何设置?

  • 版本号取自项目根目录下 package.json 的 version 字段,请直接修改该文件;

4. 生成的安装包很大(约 100MB+)

  • 正常,Electron 包含完整 Chromium 内核,且包含 node_modules;node_modules 部分已经过优化系统自动合并与清理,仍可通过 build.compression: 'maximum' 压缩,或使用 excludeDependencies 精简依赖;Windows 安装程序还可调整 Inno Setup 的压缩设置;
  • 若关闭优化(optimize: { enabled: false }),node_modules 将保持原始内容,安装包明显变大--这是关闭优化的代价;

5. 我的 excludeFiles 中的规则在打包阶段也生效了,如何避免?

  • 这是设计行为:excludeFiles 会自动转换为 electron-builder 的排除规则(前缀 !), 因此同时在复制与打包阶段生效--排除的文件不应出现在最终产物中,无需避免.

6. Windows 安装程序为什么使用 Inno Setup 而不是 NSIS?

  • 从 v4.0.0 起,Windows 安装程序改用 Inno Setup,因为它提供更强大的自定义能力和更现代的向导界面,并且安装速度极快;
  • 如果您仍需要 NSIS,可以考虑使用旧版本(v4.0.0以下);

7. 旧版 desktopAppConfig.js 在 electron-builder v27 下报错怎么办?

从本包 v5.0.0 起,底层依赖的 electron-builder 为 v27,该版本对配置格式做了破坏性调整;若你的 desktopAppConfig.js 是按旧版 electron-builder(v26)编写的,会看到类似报错:

Your configuration uses an option that was removed in electron-builder v27:

`npmRebuild` was replaced by `nativeModules.npmRebuild` in electron-builder v27.

需要按以下对照表手动迁移你的 desktopAppConfig.js(本包 v5.0.0 自带的模板已按新格式编写,可直接参考):

旧格式(electron-builder v26)新格式(electron-builder v27)
npmRebuild: falsenativeModules: { npmRebuild: false }
mac.identity / hardenedRuntime / entitlements 等统一移入 mac.sign;mac.notarize 仍在 mac 下
linux.syncDesktopName已移除,行为变为始终同步 .desktop 文件名与窗口类名

也可以执行官方迁移命令自动改写配置:

npx electron-builder migrate-schema

说明:此处的 v27 指的是 electron-builder 的 v27,不是本包或其他依赖包的版本;本包自身版本号为 @flun/desktop-builder 的 version 字段;

8. 构建或运行异常,怀疑是优化系统引起的,怎么排查?

node_modules 优化系统默认开启,绝大多数项目无需干预;若怀疑与优化相关,按以下顺序定位:

  1. 查看详细日志:运行 npx desktop-builder build --debug,查看优化各阶段删了哪些文件,为何删(详见 9. 调试构建),快速定位异常来源;
  2. 整体关闭:在 desktopAppConfig.js 中设置 optimize: { enabled: false },重新构建;若问题消失,说明确实与优化系统有关;
  3. 排除异常或不想优化的包:设为 optimize: { exclude: ['包名'] },只跳过该包;包名写 package.json 中 name 字段值, 可写多个;
  4. 彻底重来:删除临时目录 %TEMP%\desktop-builder-build(Windows,具体路径取决于系统), 重新构建会自动完整重装依赖并重新优化;

详细配置见 8. node_modules 优化;

9. 构建速度变慢了,是正常的吗?

  • 首次构建:需要下载并运行 esbuild(优化系统依赖),执行六阶段优化与启动验证,会比无优化时多花一些时间;
  • 后续构建:只要判断条件全部一致(依赖,运行环境,优化开关,原生编译开关,优化代码),构建会自动跳过安装与优化(缓存命中), 速度恢复;
  • 优化系统对最终用户收益显著:应用启动更快,安装包更小;若不在意这些收益,只想加快构建,可设置 optimize: { enabled: false } 关闭;

说明:optimize 状态记录在临时目录的 .deps-snapshot.json 中,依赖或环境变化会自动失效并重跑优化,无需手动清理;


许可证

ISC © 2026, flun


贡献

欢迎提交 Issue 和 Pull Request; 项目地址:github 中国镜像:gitee

版本与发布记录

@flun/desktop-builder 共发布 62 个版本,首次发布于 2026/07/03;过去 12 个月发布了 62 个版本。

版本发布日期距今
6.6.2latest2026/11/132 天前
6.6.12026/11/096 天前
6.6.02026/11/069 天前
6.5.32026/11/069 天前
6.5.22026/11/069 天前
6.5.12026/11/0510 天前

关于 @flun/desktop-builder 的常见问题

@flun/desktop-builder 是什么?

将任意 Node.js 网站一键打包为当前桌面应用('win', 'mac', 'linux')(基于 Electron),支持高度自定义配置;

如何安装 @flun/desktop-builder?

在项目目录运行 npm install @flun/desktop-builder,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 desktop-builder,可以用 npx desktop-builder 直接运行。

@flun/desktop-builder 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@flun/desktop-builder 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@flun/desktop-builder 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.12.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@flun/desktop-builder 可以商用吗?

@flun/desktop-builder 使用 ISC 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@flun/desktop-builder 的下载量有多少?

根据 npm 官方下载统计,@flun/desktop-builder 在 2026/10/15 – 2026/11/13 这 30 天内被下载 2,564 次,日均约 85 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@flun/desktop-builder 还在维护吗?

最新版本 6.6.2 发布于 2026/11/13(2 天前);至今共发布 62 个版本,其中过去 12 个月发布了 62 个;首次发布于 2026/07/03。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。