首页
/ draw.io Desktop 官方 Electron 桌面构建实战:安装选型、离线安全模型与开发发布流程

draw.io Desktop 官方 Electron 桌面构建实战:安装选型、离线安全模型与开发发布流程

2026-09-04 12:41:20作者:宣利权Counsellor

本文以 README 为主体,系统讲解 drawio-desktop 这个官方 Electron 桌面应用的定位、Windows 三种官方安装包的选择依据、其“与互联网完全隔离”的安全模型在源码中的落地方式,以及从克隆子模块、本地调试到个人构建与发布的完整开发流程。读完本文,你能够独立完成 draw.io 桌面版的选型安装、更新行为管控、命令行参数解析理解与源码级本地构建。

draw.io Desktop 应用界面截图

一、项目定位:Electron 外壳如何包裹 draw.io 核心编辑器

drawio-desktop 是基于 Electron 的图表绘制桌面应用,其本身并不实现编辑器,而是以 git 子模块的形式包裹 核心 draw.io 编辑器——仓库根目录下的 drawio/ 目录就是子模块挂载点。当前 package.json 声明版本为 31.4.2,依赖 electron ^44.1.1,并要求 node >= 22.12.0

项目采用 Apache 2.0 协议(见 LICENSE):只要不修改代码、接受“按原样提供”,即可将其用于任何目的,完全免费。

从主进程 src/main/electron.js 可以验证“离线自包含”这一设计前提。应用把编辑器目录直接拼成本地 file:// 地址加载:

// src/main/electron.js L204-L205
const codeDir = path.join(__dirname, '/../../drawio/src/main/webapp');
const codeUrl = url.pathToFileURL(codeDir).href.replace(/\/.\:\//, str => str.toUpperCase());

随后创建窗口时,向 index.html 传入一组 URL 查询参数(src/main/electron.js),其中 gapidbodghgltrbrowserpicker 等云端集成开关全部为 0mode 固定为 device——从源码结构看,这意味着桌面版默认关闭 Google Drive / OneDrive / GitHub 等在线功能,编辑器完全运行在本地文件上。此外还支持在当前工作目录放置 urlParams.json 覆盖这些参数(src/main/electron.js),为本地定制提供了官方认可的扩展点。

二、Windows 安装:三种官方安装包的选型依据

README 明确 Windows 发布三种安装包,各自权限模型不同,选型依据如下表:

文件名 类型 安装范围 权限要求 适用场景
draw.io-<version>-windows-installer.exe NSIS 安装器 per-machine,装入 Program Files 需要管理员权限 有管理权、面向全机的标准安装
draw.io-<version>.msi MSI 安装器 per-user,装入用户配置目录 不需要管理员权限 无管理员权限的受管终端
draw.io-<version>-windows-no-installer.exe 便携版 免安装直接运行 不需要管理员权限 绿色运行;不注册文件类型关联

此外,Microsoft Store(APPX)构建同样可以 per-user 安装、无需管理员权限。

这些说法与构建配置一一对应。electron-builder-win.json 中:

  • nsis.perMachine: true 印证 NSIS 包是机器级安装;artifactName 模板 ${productName}-${version}-windows-installer.${ext} 与 README 中的 exe 命名一致;
  • msi.artifactName${productName}-${version}.${ext},即 draw.io-<version>.msi
  • fileAssociations 声明了 .drawio.vsdx.mmd/.mermaid 三类文件关联——这也解释了为何 README 特别注明便携版“不注册文件类型关联”:关联依赖安装器写入注册表,免安装形态做不到。

Store 版本对应 electron-builder-appx.json,Linux/macOS 与 snap 分别由 electron-builder-linux-mac.jsonelectron-builder-snap.json 描述,package.json 中的 release-winrelease-appxrelease-linuxrelease-snap 脚本即为对应的 electron-builder 调用入口。

三、安全模型:离线隔离在源码中如何落地

README 将“安全与隔离”列为桌面版的首要设计目标,并声明:除更新流程外,应用与互联网完全隔离。以下逐条给出源码级证据。

3.1 唯一的网络行为:启动时版本检查

更新检查基于 electron-updater。启动时触发检查(src/main/electron.js):

safeUpdaterCall('checkForUpdates (boot)', () => autoUpdater.checkForUpdates());

下载与安装策略被刻意收紧(src/main/electron.js):autoDownload = false——永远由代码显式调用 downloadUpdate(),从而在“静默更新”与“交互式更新”之间分支;autoInstallOnAppQuit = silentUpdate——静默模式下退出应用时自动安装。

完全关闭更新检查(例如集中管控的企业部署)的两种官方方式:

  • 设置环境变量 DRAWIO_DISABLE_UPDATE=true
  • 启动时传 --disable-update

对应实现(src/main/electron.js):

const disableUpdate = disUpPkg() ||
					process.env.DRAWIO_DISABLE_UPDATE === 'true' ||
					process.argv.indexOf('--disable-update') !== -1 ||
					fs.existsSync('/.flatpak-info'); // flatpak 沙箱内自动禁用
const silentUpdate = !disableUpdate && (process.env.DRAWIO_NO_SILENT_UPDATE !== 'true' &&
										process.argv.indexOf('--no-silent-update') === -1);

其中 disUpPkg() 来自 src/main/disableUpdate.js,是一个由构建脚本生成的开关(默认返回 false,可由 sync 流程改写为 true);/.flatpak-info 的存在则说明运行在 Flatpak 沙箱中,更新机制同样被禁用。另外两个相关开关是 DRAWIO_NO_SILENT_UPDATE=true--no-silent-update:不禁用更新,但改为下载前提示而非静默更新。更新失败时,notifyUpdateFailure() 会以去重方式弹出手动下载指引,避免重复弹窗(src/main/electron.js)。

3.2 自包含的 JavaScript 与强制 CSP

README 称“所有 JavaScript 文件自包含,CSP 禁止运行远程加载的脚本”。主进程在 app.whenReady() 后通过 webRequest.onHeadersReceived 对全部响应强制注入 CSP(src/main/electron.js):

'Content-Security-Policy': ['default-src \'self\'; script-src \'self\' \'wasm-unsafe-eval\'; connect-src \'self\'' +
	(isGoogleFontsEnabled? ' https://fonts.googleapis.com https://fonts.gstatic.com' : '') +
	'; img-src * data:; media-src *; font-src * data:; frame-src \'self\'; style-src \'self\' \'unsafe-inline\'' +
	(isGoogleFontsEnabled? ' https://fonts.googleapis.com' : '') +
	'; base-uri \'none\';child-src \'self\';object-src \'none\';']

要点:

  • script-src 'self':只允许本应用目录内的脚本;'wasm-unsafe-eval' 是为内联的 libavoid WASM 边路由器编译所需;
  • connect-src 'self':把应用自身的网络连接限制到自身;
  • 仅在用户显式开启 Google Fonts(isGoogleFontsEnabled,默认 false,持久化于 electron-store)时才向 fonts.googleapis.com / fonts.gstatic.com 放开。

与此同时,onBeforeRequest 拦截所有 file://* 请求,阻止加载应用目录之外的本地文件(src/main/electron.js);IPC 侧再由 validateSender() 校验消息发送方 frame 的 URL 必须位于应用代码目录之下(src/main/electron.js),配合 contextIsolation: truewebviewTag: falsewebSecurity: true 的窗口配置(src/main/electron.js),构成多层防御。

3.3 数据外发边界与一个已知例外

README 明确:图表数据永远不会外发,也没有任何应用使用分析被发送到外部;CSP 把网络能力收敛到“自身”。但有一个需要了解的例外:图表可以引用外部媒体(如嵌入 URL 的图片、背景或字体),打开图表时这些资源会被拉取以便正确渲染——因此打开不受信任来源的图表可能向被引用 URL 发起请求,从而暴露 IP 等元数据,但不会传输图表内容。

README 最后给出项目态度:任何要求默认开启外部连接的功能,答案都是“否”。此外,从源码结构看应用是单实例模型:主进程监听 second-instance 事件(src/main/electron.js),重复启动只会唤起已有实例——这在本地同时跑官方版与自编译版时尤其需要注意。

四、开发流程:克隆、运行与调试

README 给出了最小开发回路,核心前提是必须递归克隆,因为编辑器本体是子模块:

git clone --recursive https://github.com/jgraph/drawio-desktop.git

(若已克隆但未初始化子模块,执行 git submodule update --initsync.cjs 在找不到 drawio/VERSION 时会直接报错退出,提示的正是“是否使用了 --recursive 克隆”。)

运行步骤:

  1. npm install(仓库根目录);
  2. export DRAWIO_ENV=dev(README 标注为内部用途,用于开发/调试模式);
  3. npm start(即 package.json 中的 electron .);调试时使用 npm start --enable-logging

DRAWIO_ENV=dev 的作用在 src/main/electron.js 中可见:__DEV__ 为真时,queryObjdev/test 置 1,并且 createWindow() 会为每个窗口自动打开 DevTools(src/main/electron.js)。

README 还有一条容易踩坑的说明:如果不用子模块而是用符号链接指向 drawio 仓库,必须把 drawio/src/main/webapp 内的 node_modules 目录一并符号链接。

仓库自带单元测试,覆盖 CLI 参数解析、MSI 工程构建钩子与窗口边界恢复三个模块(package.jsontest 脚本):

npm test
# 等价于 node --test src/test/cli-args.test.js src/test/msi-project-created.test.js src/test/window-bounds.test.js

例如 src/test/cli-args.test.js 验证了 format 默认 pdfembed-svg-fonts 默认 true、页码区间由 1 起始换算为 0 起始内部索引等行为。

4.1 命令行导出:桌面版附带的批量导出能力

桌面版同时是 CLI 工具,drawio [options] [input file/folder]... 支持批量导出。全部选项定义在 src/main/args.jsOPTION_DEFS 表中,常用项摘录:

参数 说明
-x, --export 按给定选项导出输入文件/目录,除 draw.io 文件外还支持 vsdx、csv、Mermaid(.mmd/.mermaid)
-o <file/folder> 输出文件/目录;省略时按输入名加格式扩展名输出
-f <format> 输出格式 pdf/svg/png/jpeg/jpg/xml/html(默认 pdf;若输出名带扩展名则以此为准)
-t / -e / -b <n> 透明背景(PNG/SVG)/ 内嵌图表副本 / 边框宽度(默认 0)
-s <scale>--width--height 缩放与按宽/高适配(保持纵横比)
-a, --all-pages 导出所有页(PDF/HTML)
-p <pageIndex>-g <from>..<to> 指定页/页码区间(1 起始,PDF 格式支持区间)
--theme <dark|light|auto> 导出主题(默认 auto),覆盖已废弃的 --svg-theme
-r, --recursive 目录输入时递归处理子目录
-k, --check 不覆盖已存在的文件
--layout <name|json> 打开后先执行布局(verticalFlow 等预设或自定义 JSON 序列)

解析器还兼容 -fpng 这类短参数粘连写法,以及 --flag=value 内联语法(src/main/args.js),以兼容旧脚本(如 Makefile 中的 drawio -xa --crop)。目录批量导出时只收集可识别扩展名(.drawio/.dio/.xml/.csv/.vsdx/.mmd/.mermaid/.png/.svg/.pdf),扫描到的 PNG/PDF/SVG 若无内嵌图表数据会跳过而不中断批次(src/main/electron.js)。

4.2 个人构建:fork 后构建未签名应用

README 指向 doc/BUILDING_FOR_PERSONAL_USE.md,其要点是:官方二进制由 GitHub Actions 发布工作流产出,依赖私有基础设施完成签名与公证(Apple Developer 证书、Azure Trusted Signing 等),fork 不具备这些条件,因此个人构建是未签名的,需要显式设置 DRAWIO_UNSIGNED=true 跳过签名与公证——这本身即是对“系统会警告未签名应用”的确认。

打包前先同步版本并禁用自动更新:

npm install
npm run sync -- disableUpdate

syncsync.cjs)做两件事:把子模块 drawio/VERSION 中的版本号写入 package.json,并按参数重写 src/main/disableUpdate.js 的返回值——禁用自动更新是为了防止个人构建被“静默更新”回官方原版、悄悄抹掉你的修改。

各平台构建命令(输出到 dist/):

  • macOS:DRAWIO_UNSIGNED=true CSC_IDENTITY_AUTO_DISCOVERY=false npx electron-builder --config electron-builder-linux-mac.json --mac dmg --arm64 --publish never(Intel 机器改 --x64;拷贝到其他 Mac 需 xattr -cr /Applications/draw.io.app 清除隔离标记)
  • Windows:$env:DRAWIO_UNSIGNED="true"; npx electron-builder --config electron-builder-win.json --publish never(注意 NSIS 安装器是机器级的,会替换官方安装)
  • Linux:npx electron-builder --config electron-builder-linux-mac.json --linux AppImage deb --x64 --publish never(Linux 不签名,无需该变量)

该文档还强调:npm run release-* 脚本是给 CI 用的(除 release-snap 外会向 releases 发布产物),本地构建应直接调用 electron-builder;若没有对应平台的机器,也可以利用 fork 上的 personal-build.yml 工作流在 Actions 中构建并下载产物。

五、发布流程:版本号同步与签名链路

README 记录了官方发布的 7 步流程:

  1. 更新 draw.io 子模块并推送变更,推送前打版本 tag;
  2. 等待构建完成(历史上由 Travis CI 负责 macOS/Linux、AppVeyor 负责 Windows,见 DEVELOPMENT.md 中对 CI 工作流、GH_TOKEN/CSC_LINK/CSC_KEY_PASSWORD 环境变量与证书导出的完整说明);
  3. 到仓库 releases 页编辑预览版发布;
  4. 下载 Windows exe 与 portable,用 signtool 签名: signtool sign /a /tr http://rfc3161timestamp.globalsign.com/advanced /td SHA256 c:/path/to/your/file.exe
  5. draw.io-windows-installer-x.y.z.exedraw.io-windows-no-installer-x.y.z.exe 重新上传签名后的文件;
  6. 补充发布说明;
  7. 正式发布。

当前仓库中这条链路的自动化程度可以进一步验证:electron-builder-win.jsonwin.signtoolOptions 指定了 build/sign-trusted.mjs 作为签名脚本、sha256 哈希算法,并用 afterPack/msiProjectCreated 钩子处理 fuses 与 MSI 工程调整(后者正是 src/test/msi-project-created.test.js 的测试对象)。而 doc/BUILDING_FOR_PERSONAL_USE.md 明确:官方二进制现由 GitHub Actions 发布工作流产出,tag 触发的发布工作流依赖私有 drawio-dev 仓库与签名密钥,在 fork 上无法运行——这解释了为什么个人构建必须走 DRAWIO_UNSIGNED 旁路。完整发布细节可另见 doc/RELEASE_PROCESS.md

六、本地存储位置与运行时数据

README 指明 Local Storage / Session Storage 落在各平台的 AppData 目录:

  • macOS:~/Library/Application Support/draw.io
  • Windows:C:\Users\<USER-NAME>\AppData\Roaming\draw.io\

从源码结构看,同一 userData 目录下还存放 electron-store 的配置数据,主进程会持久化:窗口上次尺寸与位置(lastWinSize,默认 1200,800,0,0,false,false)、拼写检查开关(macOS 默认开启)、Google Fonts 开关、以及经可信 UI 授权过的文件路径集合 blessedPaths(上限 500 条,用于限制渲染进程可写入的路径,见 src/main/electron.js)。窗口位置恢复逻辑(防止显示器变化后窗口落在屏外)由 src/main/window-bounds.js 实现,并有 src/test/window-bounds.test.js 覆盖。

七、支持政策与贡献边界

README 对支持政策表述克制:支持基于合理商业约束提供、但无合同约束;所有支持只通过本仓库进行,非付费用户没有私有工单渠道;购买 draw.io for Confluence/Jira 不包含桌面版的商业支持。

关于贡献,项目明确不开放外部贡献(“Not open-contribution”):项目复杂度决定了即使简单改动也可能破坏大量联动部件,所需测试量远超表象;即便收到 PR 也基本会推倒重写。维护者长期保持这一决定以保障项目可持续运营,同时欢迎社区提交 bug 报告与功能请求。这也与 Apache 2.0 协议并存——闭源贡献不等于限制使用:fork、修改、自用于个人构建始终被 doc/BUILDING_FOR_PERSONAL_USE.md 视为合法路径。

小结

drawio-desktop 的价值不在功能堆叠,而在工程克制:一个仅数千行主进程的 Electron 外壳,把“离线、自包含、可审计”做成了可验证的事实——CSP 头、file:// 拦截、IPC 发送方校验、更新开关链都能在 src/main/electron.js 中逐行对照。对企业部署而言,DRAWIO_DISABLE_UPDATE 与三种 Windows 安装包的权限差异是落地决策的关键;对二次开发者而言,--recursive 克隆 + DRAWIO_UNSIGNED=true + npm run sync -- disableUpdate 就是一条可复现的个人构建链路。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
903
1.82 K
docsdocs
暂无描述
Markdown
888
5.78 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.51 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.17 K
341