draw.io 与 Excalidraw 架构图版本化、协作与安全手册
一张“只有 PNG”的架构图为什么会拖慢故障处理
值班群里流传着一张网关拓扑 PNG。图上仍写着旧域名,源文件在离职同事的个人网盘里,图片中的数据库截图还带着真实实例名。故障发生后,开发只能在截图上画红圈;修订版被命名为“最终版-真的最终版”,没人知道哪张图对应正在运行的系统。
问题不在于线条是否漂亮,而在于图没有进入工程生命周期。一个可维护的图至少有两类产物:编辑器能重新打开的源文件,以及网页、评审单和文档能稳定展示的导出物。源文件负责继续演进,导出物负责阅读和分发;二者都要能追到同一个提交。draw.io 更适合结构严谨、组件较多、需要精确对齐和稳定导出的图,Excalidraw 更适合设计会、故障讨论和快速表达。草图一旦成为长期事实,就应整理结构、补齐关系语义,再进入受控的源文件与发布链路。
动手前准备一个测试仓库、Git、浏览器和 VS Code。桌面程序只从项目发布页下载安装包,VS Code 扩展则先检查发布者、权限、更新时间和仓库,再由团队锁定扩展标识。任何实验都使用 your-project、api.example.com 和虚构网段,不把生产域名、账号、IP、截图或访问令牌放进图中。
先选对编辑入口
draw.io:桌面、网页和 VS Code 是三种不同的信任边界
网页入口是 app.diagrams.net。打开后先选择保存位置:本机设备、GitHub、GitLab、Google Drive、OneDrive 等位置决定了数据最终由谁保管。draw.io 采用自带存储位置的模式,编辑器不是文件保险箱;云盘权限、Git 仓库权限和共享链接才是真正的数据边界。
受限网络或敏感图优先使用 draw.io Desktop 官方发布页。官方桌面程序支持 Windows、macOS 和 Linux,Windows 提供安装器、MSI 和免安装构建。下载后先核对发布页的版本与校验值,再安装并执行:
打开 Help > About,记录实际版本。新建空白图,保存为 docs/architecture/context.drawio。断开网络后重新打开、编辑并保存。
关闭程序后再打开文件,确认形状、连接线和中文字体仍正常。
桌面版除更新检查外按离线隔离设计;集中管理的开发机可以设置 DRAWIO_DISABLE_UPDATE=true 或使用 --disable-update,由软件分发系统统一升级。禁用自动更新后,安全修复也不会自动到达,因此必须有 owner 定期核对桌面版本与安全说明。
在 VS Code 中搜索 Draw.io Integration 时,确认发布者为 Henning Dieterichs。这是 draw.io 官方文档推荐的第三方集成,不是 JGraph 发布的官方扩展。安装后创建 context.drawio,文件应直接打开图形编辑器;命令面板执行 Reopen Editor With... 可以在图形编辑器和文本编辑器之间切换。扩展支持 .drawio、.dio 和 .drawio.svg 等格式,离线能力与具体扩展版本有关,团队应把扩展 ID 和允许版本写入工作区建议,而不是让每个人搜索相似名称自行安装。
{
"recommendations": [
"hediet.vscode-drawio"
]
}保存为 .vscode/extensions.json 后,提交前检查扩展没有获得不必要的远程访问或工作区执行权限。插件更新属于代码供应链变更,先在测试仓库打开一份副本,验证保存后没有大面积重写,再推广到团队。
Excalidraw:网页 PWA 是桌面体验,VS Code 仍是第三方入口
Excalidraw 网页版支持 PWA、离线使用、浏览器本地优先保存、实时协作和端到端加密。浏览器地址栏或应用菜单出现“安装应用”时,可以把它安装为桌面 PWA;这不是一个独立原生桌面安装包,缓存清理、浏览器配置重置和设备迁移都可能影响只存在浏览器中的场景。第一次绘图后立刻执行 Save to...,保存为 docs/architecture/incident-flow.excalidraw,不要把浏览器自动保存当作仓库备份。
VS Code 可安装发布者 pomdtr 的 Excalidraw 扩展,扩展 ID 为 pomdtr.excalidraw-editor。它是社区集成,支持 .excalidraw、.excalidraw.json、.excalidraw.svg 和 .excalidraw.png。团队配置可以写成:
{
"recommendations": [
"pomdtr.excalidraw-editor"
]
}如果需要共享团队图形库,再增加工作区相对路径:
{
"excalidraw.workspaceLibraryPath": "docs/architecture/library/team.excalidrawlib",
"excalidraw.image": {
"exportScale": 2,
"exportWithBackground": true,
"exportWithDarkMode": false
}
}相对路径能随仓库移动;绝对路径会把个人目录写进配置。exportScale 影响位图尺寸和仓库体积,背景与暗色选项会影响文档主题下的可读性。修改这些字段后,要重新导出一张带中文、细线和浅色标注的测试图,在实际文档背景中检查,而不能只看编辑器画布。
建立源文件与导出物的双轨目录
先创建一个小而明确的目录:
your-project/
docs/
architecture/
README.md
source/
system-context.drawio
incident-flow.excalidraw
rendered/
system-context.svg
incident-flow.png
library/
team.excalidrawlib
.vscode/
extensions.jsonsource/ 是事实源,rendered/ 是发布物。文档始终引用 rendered/,避免站点构建器误把编辑器私有格式当图片。每次修改源文件时,同一提交更新导出物;评审者既能看视觉变化,也能确认源文件仍可编辑。
draw.io 默认源格式使用 .drawio XML。PNG、SVG 和 PDF 可以选择嵌入图数据,但“图片里藏着源文件”会让职责变模糊:代码仓库默认提交独立 .drawio 源文件与普通 SVG/PNG;只有确实需要单文件交付时才启用嵌入图数据,并在文件名和 README 中说明。
Excalidraw 的 .excalidraw 是开放 JSON 格式。它比二进制文件更容易检查,但拖动形状会改变坐标、版本和应用状态,Git diff 仍可能很大。不要手工格式化、排序或批量重写 JSON;编辑器可能依赖元素顺序、绑定关系和文件映射。评审以渲染差异为主,以 JSON 中的文本、链接和资源字段为安全检查入口。
在 docs/architecture/README.md 记录图与系统事实的绑定关系,而不是写一篇绘图教程:
| 图 | 事实源 | 发布物 | owner | 触发更新的变更 |
| --- | --- | --- | --- | --- |
| 系统上下文 | source/system-context.drawio | rendered/system-context.svg | platform-team | 外部系统、信任边界或主要调用关系变化 |
| 故障流程 | source/incident-flow.excalidraw | rendered/incident-flow.png | service-team | 告警入口、处置步骤或升级路径变化 |owner 是维护责任,不是个人署名。人员变化时只改团队角色;图的提交历史继续保留。
做一次可复制的正向实验
draw.io 从源文件到可追踪 SVG
在 system-context.drawio 放入三个框:User、Web Application、Orders API。两条箭头分别写 HTTPS request 和 JSON/HTTPS,不要只写 uses。给图加标题、图例和 source commit: <short-sha> 占位文本。
选择 File > Export as > SVG。关闭 Include a copy of my diagram,打开透明背景或按站点主题选择背景,导出到 rendered/system-context.svg。在浏览器和站点预览中打开 SVG,放大到 200%,检查中文、箭头、字体和边界。
用文本工具做最小证据检查:
git add docs/architecture/source/system-context.drawio \
docs/architecture/rendered/system-context.svg
git diff --cached --stat
git diff --cached -- docs/architecture/source/system-context.drawio
rg -n "api\.example\.com|10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\." docs/architecture预期看到两个文件同时进入暂存区,XML diff 中能找到刚修改的标签,敏感地址扫描没有命中。若 SVG 在浏览器正常、站点中却缺字,通常是字体没有嵌入、站点禁止 foreignObject,或导出时保留了目标平台不支持的文本格式。处理顺序是换成团队允许的本地字体、关闭文本格式化/自动换行后重导出,再在目标渲染器复测。
Excalidraw 从协作草图到仓库文件
在空场景中画 Alert、On-call、Rollback 三个元素。用带方向的箭头写清 pages 和 executes。通过 Save to... 保存 incident-flow.excalidraw。
通过导出面板导出 2 倍 PNG 到 rendered/incident-flow.png。关闭网页,重新打开保存的 .excalidraw,移动一个节点后再保存。
检查文件确实包含源数据且没有明显秘密:
git diff --numstat -- docs/architecture/source/incident-flow.excalidraw
rg -n '"type"|"elements"|"files"|"link"' \
docs/architecture/source/incident-flow.excalidraw
rg -n "token|password|secret|BEGIN .*PRIVATE KEY|internal\.example" \
docs/architecture/source/incident-flow.excalidraw预期 JSON 中存在 type、elements 等结构,PNG 能在普通图片查看器中打开,秘密扫描没有真实命中。若 files 字段包含很长的 data URL,说明图片资源已经嵌入源文件;这会增加仓库体积,也可能把截图中的隐私永久写进 Git 历史。
再故意制造一次失败
反例一:只改导出物
在图片编辑器上给 system-context.svg 加一个“临时网关”,但不改 .drawio。然后执行:
git status --short docs/architecture
git diff -- docs/architecture/rendered/system-context.svg故障证据是只有 rendered/system-context.svg 变化。合并后,下一个人从 .drawio 重导出时,“临时网关”会消失。这不是普通文档遗漏,而是两个事实源互相竞争。修复方式是撤销对导出物的直接编辑,在源文件中完成修改,再重新导出。
反例二:两个人同时编辑同一个画布文件
从同一提交创建两个分支,两边分别移动不同节点并保存,再尝试合并。draw.io XML 或 Excalidraw JSON 很可能出现冲突;即使 Git 自动合并成功,元素绑定、坐标和连接线也可能形成视觉错误。
git diff --check
git diff --name-only --diff-filter=U如果存在未合并文件,不能用“保留双方”机械解决。指定一名图 owner 在编辑器中打开基线,逐项重做双方有价值的视觉修改,保存后重新导出并让另一名作者复核。实时协作适合多人同时讨论;Git 分支适合串行审查。两种并发模型叠加在同一个文件上,冲突成本最高。
反例三:外链资源在评审时消失
在图中插入 https://assets.example.com/private/icon.png,然后在无登录状态或离线环境打开。常见证据是空白框、跨域错误、鉴权失败或导出图缺图。将获准分发的资源嵌入源文件可以提升可移植性,但会增加文件大小;将资源保存在仓库并由构建流程复制,则更容易审计许可证和复用。涉及云厂商图标时,还要保留来源与许可,不要从搜索结果随意复制。
导出不是“另存为”那么简单
选择格式时先看消费端:
| 产物 | 适合 | 主要代价 |
|---|---|---|
| SVG | 技术站点、可缩放文档、清晰文字 | 平台可能过滤脚本、链接、foreignObject 或字体 |
| PNG | 工单、聊天、兼容性优先的页面 | 放大会失真,分辨率与仓库体积一起增长 |
| 评审包、打印和归档 | 字体、分页、裁剪和服务端转换边界要复测 | |
| 带源数据的 PNG/SVG | 单文件交付且接收方需要继续编辑 | 文件更大,隐藏的源数据也会被一起分发 |
draw.io 支持在 PNG、SVG 和部分 PDF 中嵌入图数据;Excalidraw 及其 VS Code 扩展也能生成带可编辑数据的 .excalidraw.png 和 .excalidraw.svg。发布到公共站点前必须明确是否保留嵌入源。源数据可能包含被画布遮住的旧文本、链接、元素元数据和嵌入图片,肉眼看不到不等于文件里不存在。
对外导出后至少做四项检查:
file docs/architecture/rendered/*
git diff --check
rg -n "https?://|data:image|password|token|secret" docs/architecture
git status --short docs/architectureWindows 没有 file 时,用文件属性和浏览器打开验证。SVG 还应经过站点现有的 SVG 安全处理;不要因为它是“图片”就跳过脚本、外链和元数据检查。
协作要先决定谁拥有最终写入权
draw.io 的实时协作依赖具体存储集成。Google Drive、OneDrive、Confluence Cloud,以及满足条件的 Nextcloud 可以提供实时协作;GitHub、GitLab、Dropbox 或网络盘更接近保存时同步与合并。网络变慢或冲突频繁时,可以关闭实时同步,改成明确的单人写入窗口。桌面版不直接提供云盘账号体系,它只编辑本机或同步目录中的文件。
Excalidraw 免费网页的实时房间适合设计会。房间链接同时承载访问入口和解密材料,后端不保存解密密钥并不意味着链接可以公开转发。把链接贴进公开 issue、录屏、浏览器同步历史或日志,等价于扩大访问范围。会议结束后应导出源文件、结束共享语境,并按信息等级决定是否需要迁移到受控仓库或团队工作区。
需要持久场景、文件夹、评论、访问管理、只读链接或团队管理时,应在采购前查看 Excalidraw+ 价格与能力页。座席价格、试用和功能会变化,预算评审读取目标租户页面,不把金额写进仓库规范。自托管开源编辑器也不自动得到完整协作、身份、审计和持久化;官方 npm 组件与自托管前端需要团队自行补协作后端、认证、备份、升级和安全响应,这通常比购买座席更昂贵。
敏感架构图按数据而不是工具分级
“使用了端到端加密”只能解释传输和服务端可见性的一部分。终端截图、浏览器缓存、导出的源文件、Git 历史、共享链接和接收者权限仍然存在。将图按内容分级更可靠:
公开图只展示公开组件和文档链接,可以进入公共仓库。内部图包含内部服务名和非公开依赖,只进入受控仓库,导出物也继承同级权限。受限图包含安全区、管理入口、应急路径或供应商细节,优先离线桌面编辑、加密存储、最少接收者和访问审计。
秘密本身不进图。令牌、私钥、密码、真实 Cookie 和完整连接串应留在密钥系统;图只写 <secret-ref>、Secret Manager 或凭证流向。
draw.io Desktop 适合离线处理受限图,但同步目录、磁盘备份和导出动作仍需受控。draw.io 网页可以启用 lockdown 配置减少非存储目标的数据传输,不过 PDF 转换、部分导入和在线能力会受影响。Excalidraw 场景若嵌入截图,应在导入前裁剪并脱敏;删除画布上的图片后,还要重新保存并检查 files,确认源 JSON 没有继续携带旧资源。
文件为什么会越来越大
draw.io XML 保存形状、样式、页面、连接关系和资源;Excalidraw JSON 保存元素、应用状态以及按文件 ID 引用的嵌入资源。真正拉大文件的通常不是矩形,而是截图、背景图、字体替代和多页历史副本。
容量治理不使用统一的“不得超过某个固定值”,而看趋势和用途:纯矢量源文件在连续修改中突然成倍增长,应检查嵌入资源;同一截图是否在多个图中重复嵌入;导出 PNG 是否使用了远高于消费端需求的倍率;仓库 clone 和站点构建时间是否随图集单调增长。大二进制资源可以进入受控资产库或 Git LFS,但 LFS 会引入存储、流量、权限和退出成本,先测量再采用。
长期维护时,每个图都绑定触发事件:服务拆分、外部依赖变化、网络信任边界变化、协议变化、部署拓扑变化和重大故障复盘。PR 模板要求作者回答“哪些图受影响”;CI 至少检查源文件与导出物是否配对、敏感模式是否命中、引用路径是否存在。视觉正确性仍需人工评审,因为 XML/JSON 合法并不能证明箭头方向、抽象层级和文字可读。
清理、回滚与退出
个人实验完成后:
git restore --staged docs/architecture
git clean -nd docs/architecture/renderedgit clean -nd 只预览未跟踪文件;确认目录内没有他人产物后,才针对精确文件执行删除。不要在共享仓库运行宽泛的 git clean -fd。
回滚一次错误绘图提交时,优先对该提交执行常规 Git 回退,让源文件和导出物一起回到上一状态。若只恢复源文件,必须立刻重新导出,否则双轨再次分叉。协作平台上的共享链接还要单独撤销;删除仓库文件不会撤销云盘权限,也不会从 Git 历史抹掉曾提交的秘密。
退出某个编辑器前,用另一台干净设备完成可移植性演练:打开源文件、检查字体和嵌入资源、导出 SVG/PNG、验证文档引用、撤销旧共享权限。能在没有原作者浏览器缓存和个人素材目录的情况下完成这条链路,图才真正属于团队。
合并前的工程验收
一次合格的图变更应满足这些可观察事实:源文件能重新打开,导出物能在目标文档中显示,源与导出物位于同一提交;图中的标题、箭头方向、关系标签和图例足以脱离口头讲解;扫描没有发现真实凭证、内网地址或遗留截图;第三方扩展和在线协作入口经过准入;冲突由图 owner 在编辑器中重建并复核;容量增长可以解释;删除、回滚和权限撤销都有明确责任人。
工具选择也因此变得直接:短时共同思考优先 Excalidraw,结构化长期图优先 draw.io;需要同一模型生成多张一致的架构视图时,继续采用 C4/Structurizr 一类模型化工具,而不是在多个画布里复制相同方框。画布工具擅长表达,模型工具擅长保持语义一致,二者可以衔接,但不应互相冒充。
