drawio-desktop 开发指南:从仓库结构、版本同步到多平台构建与代码签名
本篇基于 drawio-desktop 仓库的 DEVELOPMENT.md 展开,讲解这个官方 Electron 外壳仓库的组成与发布工作流:它如何通过 drawio 子模块获取版本号、如何用 electron-builder 打包 Windows/macOS/Linux 安装包、CI 如何自动发布安装器,以及 Windows 与 macOS 代码签名的证书要求与配置方式。读完你可以完整理解"推送提交 → CI 构建 → 安装器上传 → 人工发布"这条流水线的每个环节,并能独立配置签名环境变量。
仓库定位:Electron 外壳 + draw.io 子模块
drawio-desktop 是 draw.io 的官方 Electron 桌面构建仓库,它本身不包含编辑器核心代码——核心图表编辑器(webapp)以 git 子模块形式放在 drawio/ 目录下。从 .gitmodules 可以看到:
[submodule "drawio"]
path = drawio
url = https://github.com/jgraph/drawio.git
branch = dev
DEVELOPMENT.md 在 Setup 一节列出的仓库资源结构(原文指向旧的独立 installer 仓库 mediaslav/drawiodesktop,当前仓库中对应物如下):
| 文档提到的目录/文件 | 当前仓库中的对应物 | 作用 |
|---|---|---|
build/(安装包资源,禁止改名) |
build/ | 各尺寸图标(icon.ico/icns/各 PNG)、签名与公证脚本 fuses.mjs、notarize.mjs、sign-trusted.mjs 等 |
electron-builder.json(主构建配置) |
electron-builder-win.json、electron-builder-linux-mac.json、electron-builder-appx.json、electron-builder-snap.json、electron-builder-win-arm64.json | 拆分为按平台区分的多份 electron-builder 配置 |
sync.js(从 ./draw.io/VERSION 取版本) |
sync.cjs | 读取 drawio/VERSION 并写回 package.json |
.travis.yml / appveyor.yml(CI 配置) |
.github/workflows/ 下的 electron-builder.yml、electron-builder-win.yml 等 GitHub Actions 工作流 |
Travis/AppVeyor 已迁移到 GitHub Actions |
draw.io/ 子模块 |
drawio/ 子模块 | 编辑器 webapp 来源 |
因此克隆仓库必须带 --recursive(或事后执行 git submodule update --init),否则 sync.cjs 会直接报错退出——源码中可以看到这一防护:
if (!fs.existsSync(versionPath))
{
console.error('Error: drawio/VERSION not found. Did you clone with --recursive or run git submodule update --init?')
process.exit(1)
}
见 sync.cjs。
版本号的单一事实来源
DEVELOPMENT.md 的 High level workflow 中强调:构建器会使用 ./draw.io/VERSION 中的版本号,忽略 draw.io/war/package.json 里的 version。这一机制在当前仓库由 sync.cjs 实现:
- 读取
drawio/VERSION并trim(); - 用正则
/^\d+\.\d+\.\d+$/校验必须是x.y.z格式,否则报错退出; - 把该版本写回 package.json 的
version字段; - 同时生成 src/main/disableUpdate.js——根据命令行参数
disableUpdate决定disableUpdate()返回true还是false,即控制打出来的安装包是否禁用自动更新。
npm run sync # 正常同步(自动更新开启)
npm run sync -- disableUpdate # 禁用自动更新(个人构建推荐)
从 package.json 的 scripts 可以看到 sync 就是 node ./sync.cjs,而当前 package.json 中的 version: 31.4.2 正是由该脚本从子模块 VERSION 文件 stamp 进来的。
发布工作流:push → CI 构建 → 草稿 release → 人工发布
DEVELOPMENT.md 给出的四步高层工作流是理解整个仓库发布机制的主线:
- 向仓库推送提交;
- git hook 触发 CI 执行构建(构建器使用
./draw.io/VERSION中的版本); - 构建成功后 CI 在 GitHub 上起草(draft)一个新 release 并上传安装器——原文档时代是 mac/linux 走 Travis、Windows 走 AppVeyor,当前仓库中对应 .github/workflows/electron-builder.yml(macOS/Linux)与 .github/workflows/electron-builder-win.yml(Windows,含 Azure Trusted Signing)两个工作流;
- 等所有平台的安装器都进入草稿后,人工点 "Publish release" 正式发布。
原文档还保留了两个实操细节:发布前要在 releases 页面打开对应 draft,点 "Edit",确认所需安装器全部上传完毕后再 "Publish release";以及 "Travis OSX builds can spend hour(s) in queue"(macOS 构建可能排队数小时)——这解释了为什么需要等所有平台安装器集齐再发布。整体设计可以概括为:机器做构建,人只做 push 和按发布按钮。
发布前置条件(来自 package.json)
engines要求 Node.js>=22.12.0(package.json);- 构建产物统一输出到
./dist/(各 electron-builder 配置的directories.output); - 所有安装包启用
asar: true,且files统一排除**/WEB-INF{,/**}目录(Tomcat 遗留目录,不需要打包进桌面应用)。
平台构建命令与 electron-builder 配置
package.json 中的 scripts 定义了各平台发布命令,每条都显式指定对应的 electron-builder 配置文件:
| 命令 | 配置文件 | 目标产物 | --publish 行为 |
|---|---|---|---|
npm run release-win |
electron-builder-win.json | NSIS 安装器 + MSI(x64) | always |
npm run release-win-arm64 |
electron-builder-win-arm64.json | Windows ARM64 | always |
npm run release-appx |
electron-builder-appx.json | Windows Store appx | always |
npm run release-linux |
electron-builder-linux-mac.json | AppImage / deb / rpm(x64 + arm64),同一配置也用于 macOS zip/dmg | always |
npm run release-snap |
electron-builder-snap.json | snap(core24 基础) | never |
npm start |
— | 本地 electron . 运行 |
— |
npm test |
— | Node 内置测试运行器跑 src/test/ 三个用例 | — |
几个值得注意的配置细节:
- Windows 文件关联:electron-builder-win.json 中
fileAssociations声明了.drawio(application/vnd.jgraph.mxfile)、.vsdx、.mmd/.mermaid三类扩展名以 Editor 角色关联,Linux/macOS 配置中也有对应的声明(macOS 侧通过CFBundleDocumentTypes与UTExportedTypeDeclarations实现,见 electron-builder-linux-mac.json)。 - macOS 双架构 + universal:dmg 目标包含
x64、arm64、universal三种架构;entitlements与entitlementsInherit均指向 build/entitlements.mac.plist,并开启hardenedRuntime。 - 签名钩子:
afterPack: build/fuses.mjs(熔断安全开关)、macOS 的afterSign: build/notarize.mjs(组装 Quick Look 扩展并公证)、Windows 的msiProjectCreated: build/msi-project-created.mjs(MSI 快捷方式图标修正)。 - snap 的 snapcraft 声明:基于
core24,挂载default、removable-media、browser-support三个 plugs(见 electron-builder-snap.json)。
配置 CI:GitHub 发布与代码签名所需的环境变量
DEVELOPMENT.md 的 "Configuring CI" 一节给出 CI 必须提供的三个环境变量:
| 变量 | 含义 |
|---|---|
GH_TOKEN |
GitHub token,用于把构建产物发布到 release |
CSC_LINK |
证书:base64 编码字符串,或指向 *.p12/*.pfx 证书文件的 URL |
CSC_KEY_PASSWORD |
解密 CSC_LINK 所用证书的密码 |
原文档按 Travis CI(macOS/Linux 安装器,在仓库 Settings 页配置)和 AppVeyor(Windows NSIS 安装器,在 SETTINGS / Environment 下 Add variable)分别说明配置入口;迁移到当前仓库后,对应的 secrets 在各 GitHub Actions workflow(.github/workflows/electron-builder.yml、.github/workflows/electron-builder-win.yml)的仓库级 secrets 中配置。
Windows 签名
原文档对 Windows 代码签名的说明至今仍适用,要点如下:
- Windows 有两类证书:EV Code Signing Certificate 与 Code Signing Certificate,两者都支持自动更新;
- 普通(通常也更便宜的)Code Signing Certificate 在安装时会显示 SmartScreen 警告,但当足够多用户安装、建立起信任后警告会消失;
- CI 上只能使用普通 Code Signing Certificate,因为 EV 证书绑定物理 USB 安全令牌,无人值守的 CI 无法操作;
- 网站用的 SSL 证书不能用于应用签名。
需要说明的是:当前仓库的 Windows 签名已从"本地证书 + CSC_LINK"演进为 Azure Trusted Signing。electron-builder-win.json 中 win.signtoolOptions.sign 指向 build/sign-trusted.mjs,并配 signExts: [".dll"] 连 Electron 自带的 DLL 一起签名;CI 端则通过 AZURE_TENANT_ID / AZURE_CLIENT_ID / AZURE_CLIENT_SECRET 等 secrets 完成身份认证(见 CLAUDE.md 的 Code Signing 小节)。也就是说,文档中"CI 只能用普通证书"的原则被 Azure Trusted Signing 方案进一步落地。
macOS 签名与证书导出
macOS 构建要求 Apple 签发的 Developer ID 证书,需成为 Apple Developer Program 成员才能获取。原文档给出的 Keychain 导出步骤完整保留:
-
打开 Keychain(钥匙串);
-
选择
login钥匙串与My Certificates分类; -
选中所需证书(可用 cmd-click 多选),按需选择:
Developer ID Application:为 macOS 应用签名;3rd Party Mac Developer Application+3rd Party Mac Developer Installer:为 Mac App Store 包签名;Developer ID Application+Developer ID Installer:为 App Store 之外的应用及安装器签名;
可以一次选择多张证书,electron-builder 侧无数量限制;所有选中的证书都会被导入 CI 服务器的临时钥匙串;
-
右键上下文菜单选择
Export。
导出后将 .p12 文件编码为 base64 供 CSC_LINK 使用(macOS/Linux):
base64 -i yourFile.p12 -o envValue.txt
当前仓库的 macOS 侧还有 build/notarize.mjs 在 afterSign 钩子中完成 Quick Look 扩展(.appex)组装、重签名与公证。
依赖警告:devDependencies 与 dependencies 的边界
DEVELOPMENT.md 结尾的 WARNING 值得所有维护 fork 的人注意:draw.io/war/package.json 的 dependencies 会被打进安装包,因此无关节的依赖必须放进 devDependencies——构建器会忽略 devDependencies。原文档给出的经典反例是把 electron 本身放进 devDependencies("显然不需要把一个 electron 作为依赖打进另一个 electron")。
这一原则同样体现在当前仓库:package.json 中 electron、electron-builder、@electron/fuses、@electron/notarize、dotenv、quicklookjs、sumchecker 等构建/工具类依赖全部位于 devDependencies,而 dependencies 只保留运行时真正需要的包(electron-updater 自动更新、electron-store 持久化设置、electron-log 日志、@cantoo/pdf-lib PDF 导出、compression、buffer、crc、electron-context-menu、tslib 等)。
本地开发速查
结合 DEVELOPMENT.md、CLAUDE.md 与 package.json scripts,本地开发的完整路径为:
# 1. 递归克隆(子模块必须初始化)
git clone --recursive https://gitcode.com/GitHub_Trending/dr/drawio-desktop.git
cd drawio-desktop
# 2. 安装依赖(需 Node >= 22.12.0)
npm install
# 3. 运行(开发模式可自动打开 DevTools)
npm start
DRAWIO_ENV=dev npm start
# 4. 构建前必须同步版本
npm run sync
npm run sync -- disableUpdate # 个人构建时禁用自动更新
# 5. 按平台构建
npm run release-win
npm run release-linux
npm run release-appx
npm run release-snap
测试方面,npm test 使用 Node 内置 test runner 运行 src/test/cli-args.test.js(CLI 参数解析)、src/test/msi-project-created.test.js(MSI 快捷方式图标钩子)与 src/test/window-bounds.test.js(窗口位置记忆)三个用例。此外 doc/BUILDING_FOR_PERSONAL_USE.md 与 doc/RELEASE_PROCESS.md 分别覆盖 fork 无签名构建与完整发布流程,是本文所依据 DEVELOPMENT.md 的自然延伸阅读。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00