
很久以前让我最头疼的不是写复杂的业务代码而是画流程图。需求评审要画技术方案要画排查线上问题复盘也要画。工具换过 Visio、ProcessOn、draw.io每次画完还得导出图片、贴到文档里改一个分支就要重新导出拉到群里问“这张是新的”。直到我把流程图从“拖拽画图”改成“写代码”也就是用 Mermaid 来画流程图这个痛点才真正解决。Mermaid 本质上是一门用纯文本描述图表的标记语言用类似 Markdown 的语法写节点和连线让渲染器自动排版成图。它擅长的正是流程图日常写技术文档、项目 README、接口设计、算法思路记录基本一套语法全搞定。非常适合以下几类人写博客和开源项目的开发者、需要频繁更新设计文档的产品和技术人以及想把算法思路讲清楚的学生或讲师。这篇文章我会从语法基础讲起再用三四个业务场景把代码一步步拆开最后把我踩过的渲染、兼容、布局方面的坑一并倒给你。1. 为什么我最终把流程图从“拖拽”改成了“写代码”1.1 代码画图解决的核心痛点先说我原来用拖拽画图最难受的三个点。第一是版本管理。我一度靠文件名区分版本流程图_v3_最终版、流程图_v4_真正最终版。有了 Mermaid 之后流程图变成一个.md或.mmd文本文件扔进 Git 仓库每次改动都能 diff。两个人改同一个流程图直接看冲突位置比肉眼对比两张图片截图高效太多。第二是复用和批量修改。拖拽工具里复制一个节点往往会连带一堆坐标信息想统一改某个节点文案得有耐心找到它。Mermaid 则像写代码一样节点就是一个 ID 对应一个标签全局搜索替换即可。多个文档要同一套流程骨架把代码片段复制过去改两个标签就行。第三是自动化。我在一些项目里用脚本把 Mermaid 代码直接生成 SVG 输出到站点文档中CI 里随代码一起构建。这需要的是代码生成的图而不是人肉截图。1.2 哪些场景该用 Mermaid哪些场景还是老老实实绘图我现在的习惯是逻辑导向的图表用 Mermaid视觉导向的图表用绘图工具。所谓逻辑导向是指图的重点在于节点之间因果、判断、流转关系比如登录流程、算法流程、订单状态流转、数据流向这些内容本质上是“一段可以读的文本”很适合用代码表达。所谓视觉导向是指对排版美感、配色、手绘风格有强要求比如汇报 PPT 里的架构图、给客户看的高保真流程示意。Mermaid 的自动布局在复杂场景下还是不如手调坐标的效果可控。强行用它画十几个节点互相交叉的图效果会很灾难。我的建议是技术文档内部用 Mermaid对外正式汇报用绘图工具中间的转换由代码完成。2. 半小时上手Mermaid 流程图的底层语法拆解2.1 graph 与 flowchart以及方向声明怎么选Mermaid 流程图有两种顶层声明graph和flowchart两者在大部分情况下可以互换flowchart是后者的推荐写法支持的节点形状和样式能力更丰富。老版本资料里多用graph所以你会看到大量graph TD开头的示例实际用下来两者差别不大建议新代码统一用flowchart。方向声明的选择直接影响图的阅读顺序TD/TB从上到下Top-Down最常用适合步骤型流程BT从下到上少数情况用LR从左到右适合时间线感强、步骤不太多的流程RL从右到左用的比较少举个例子下面这段代码是从上到下绘制“起床到出门”的流程flowchart TD A[起床] -- B[洗漱] B -- C{早饭吃什么} C --|包子| D[吃包子] C --|面条| E[吃面条] D -- F[出门] E -- F[出门]方向要根据内容选。我画用户登录流程习惯用TD因为分支判断后从上往下看很自然画组件之间的调用链时用LR因为更接近请求从左到右流经各层的直觉。不建议在一张图里混用方向小图无所谓大图容易乱。2.2 节点形状一张表说清楚节点语法统一是ID[显示文本]重点在于括号的形状。我整理了一张速查表基本覆盖日常 95% 的需求。形状语法典型用途圆角矩形A(文字)开始/结束节点流程动作矩形A[文字]普通处理步骤最常用菱形A{文字}判断分支圆形A((文字))连接点、入口、出口六边形A{{文字}}准备性操作平行四边形A[/文字/]输入/输出数据读写体育场形A文字]异步处理或外部调用子图subgraph 名分组见后面章节注意 ID 和显示文本是可以分开的。ID 用英文和数字显示文本用中文这一条对我后面的可维护性影响巨大。比如flowchart TD login[用户输入账号密码] checkEmpty[校验是否为空]这样写的好处是当图变大以后节点 ID 稳定连线逻辑清晰改中文文案不影响结构。我见过有人把整句流程直接写在 ID 位置比如A[如果用户没有输入账号就提示错误]一旦修改文案所有引用这个节点的地方都要跟着改体验极差。2.3 连线的四种写法与文字标签Mermaid 连线主要有四种样式实线箭头A -- B实线无箭头A --- B虚线箭头A -.- B粗实线箭头A B默认实线箭头用得最多。无箭头适合表示关联关系虚线适合表示数据反馈或异步通知粗线适合强调主路径。给连线加文字有两种写法flowchart TD A[发起登录] --|成功| B[进入首页] A --|失败| C[提示错误]也可以写成A-- 成功 --B效果相同。但我统一建议用|文字|这种写法它在长标签和后续 AI 生成场景下解析更稳定。连线文字里如果需要换行可以用br/这在分支条件较长时很有用比如A[发起登录] --|账号不存在br/或密码错误| C[提示错误]在实际操作中我的习惯是节点里放动作连线上放条件这样读图的人一眼就能看出“什么条件下走哪条路”。如果你把条件也堆进节点图会迅速变成一块文字墙。3. 三个高频业务场景的 Mermaid 落地示例3.1 用户管理模块流程图把权限分支画清楚“用户管理模块流程图”是搜索量很高的场景也是我工作中画得最多的图之一。这类流程图的核心是登录后做什么校验走到哪些权限分支非法路径如何兜底。下面是我常用的一个模板覆盖了登录、角色判断和异常返回flowchart TD start([开始]) -- input[输入账号密码] input -- checkEmpty{是否为空} checkEmpty --|是| error1[提示账号密码不能为空] error1 -- input checkEmpty --|否| auth[身份认证] auth --|认证失败| error2[提示账号或密码错误] error2 -- input auth --|认证成功| getUser[查询用户信息] getUser -- checkStatus{账号状态} checkStatus --|禁用| error3[提示账号已被禁用] checkStatus --|正常| checkRole{判断角色} checkRole --|管理员| adminPanel[进入管理后台] checkRole --|普通用户| userPanel[进入用户首页] checkRole --|未知角色| error4[记录日志并提示无权限] adminPanel -- endNode([结束]) userPanel -- endNode error3 -- endNode error4 -- endNode画这种图有一个经验先列节点再连边。我第一次画这种多分支图时直接写连线写到最后发现少了一个错误出口。后来我改成先在草稿纸上列清单开始、输入、判空、认证、查用户、状态判断、角色判断、各终态最后补两个兜底错误节点一气呵成。还有一点分支图的“回归边”不要省。上面错误提示之后连回输入框读者能清楚看到同一层级的重新尝试路径。没有回归边这张图就像有去无回的单向通道容易让人误以为自己看漏了一条返回路线。3.2 算法流程图循环结构与回边怎么表达算法类流程图的关键是循环。我在读算法文章或给学生讲二分查找时特别喜欢先用 Mermaid 把流程画出来因为它的回边从判断节点指回前面节点非常直观。拿经典的二分查找举例flowchart TD start([开始]) -- init[设置 left0, rightn-1] init -- loopCheck{left right?} loopCheck --|是| fail[返回 -1未找到] loopCheck --|否| mid[计算 mid left (right - left) / 2] mid -- compare{arr[mid] 与 target 比较} compare --|相等| success[返回 mid] compare --|小于 target| leftMove[左侧指针移动: left mid 1] compare --|大于 target| rightMove[右侧指针移动: right mid - 1] leftMove -- loopCheck rightMove -- loopCheck success -- done([结束]) fail -- done这段代码里有几个值得注意的练习点。第一循环回边是通过把leftMove和rightMove指回loopCheck实现的这恰好对应算法教材里的箭头返回循环判断处。新手容易犯的错误是把回边画到循环体中间导致别人读图时以为要去执行两段逻辑。第二二分查找中很多人写mid (left right) / 2在 Mermaid 图上写完整公式就行但如果你想把这个图变成代码建议标注“用防溢出写法”细节能引导读者。第三算法循环图的验证方法很重要。画完之后我习惯从 start 开始沿着每条路径走一遍确认每条路径都能到 end且每个“返回判断”的节点都确实有连线回到循环条件。这相当于静态检查流程图和读书时候做“算法 流程图 习题”的验算逻辑一模一样。另一个常见的需求是把算法流程转成“控制流图”用于分析。控制流图的核心是基本块和跳转边Mermaid 完全能表达每个矩形块是一个基本块回边就是循环对应的跳转边。你完全可以先写伪代码再转成流程图最后导出成控制流图做路径覆盖分析整个流程我用 Mermaid 走通过很多次。3.3 数据流程图用子图模拟分层架构数据流程图DFD在教科书里强调外部实体、加工、数据存储等元素但现实中我更常画的是“分层数据流图”用来表达数据从界面到逻辑层再到存储层怎么流动。这种情况下 Mermaid 的subgraph子图特别好用。以“用户注册流程”为例flowchart LR subgraph 展示层 U[用户填写注册表单] S[提交注册请求] end subgraph 逻辑层 V[数据校验] R[检查用户是否已存在] T[生成Token / 创建用户] end subgraph 存储层 DB[(用户数据库)] CACHE[(Redis缓存)] end U -- S S -- V V --|校验失败| U V --|校验成功| R R --|已存在| U R --|不存在| T T -- DB T -- CACHE CACHE --|同步缓存| T DB --|落库成功| done([注册成功])这里三个subgraph把不同的职责边界分开了视觉上比纯铺开的图好理解得多。使用子图时我提醒一点子图的名字尽量不要用中文因为它既是分组名也是渲染器内部引用的一部分。在部分平台上中文子图名会导致样式定位异常。我在上面示例里用了英文分组名但实际标签需要中文的话我会在 subgraph 定义后手动加一个说明节点。当然如果团队要求的是标准 DFD 符号体系加工用圆圈、数据存储用双线Mermaid 对这种专业性建模支持有限那种情况我建议回到专业绘图工具。但对于绝大多数日常的数据流转说明子图方案完全够用。4. 子图、主题样式与现代化渲染4.1 用 subgraph 给流程分组子图可以把一组节点包在一个框里适合划清模块边界比如“用户端”“管理端”、“前端”“后端”、“正常流程”“异常流程”。基本语法flowchart TD subgraph frontend A[页面点击] B[表单校验] end subgraph backend C[接口处理] D[数据库写入] end A -- B B -- C C -- D几点实操心得子图内可以继续嵌套子图但建议最多两层。超过两层以后渲染器的边界线会挤在一起标签位置容易偏移我试过三次嵌套最后不得不拆图。子图内如果有很多节点默认方向可能变得很扁。可以单独在子图内声明direction TB这个内部方向声明不会影响外层总体方向非常适合做“外层 LR、内部 TD”的组合布局。子图的“块”感依赖边框和背景如果你对样式有要求记得给子图也加上类和样式后面会讲到。4.2 classDef 与主题变量让图有“设计感”Mermaid 默认的流程图颜色比较朴素但可以通过两种方式美化。第一种是给节点单独加样式flowchart TD A[开始] -- B[处理] B -- C{判断} style A fill:#fff3e0,stroke:#ff9800,stroke-width:2px style C fill:#fce4ec,stroke:#e91e63,stroke-width:2px第二种是定义样式类适合多个节点统一配色flowchart TD A[读取配置]:::config -- B[校验参数]:::config C[执行任务]:::run B -- C classDef config fill:#e3f2fd,stroke:#1976d2,stroke-width:1px; classDef run fill:#e8f5e9,stroke:#43a047,stroke-width:1px;这里的:::config语法就是“应用名为 config 的类”很好理解。样式属性包括fill填充色、stroke边框色、stroke-width边框宽度、color文字色、rx/ry圆角半径等。现代 Mermaid 版本还支持主题变量常见主题有default、forest、dark、neutral。在支持的渲染平台里你可以在开头声明%%{init: {theme:dark}}%%来全局换肤。团队文档如果统一走深色模式这招非常实用。不过我在 GitHub 上实测发现部分平台的暗黑主题支持不是实时的文档里用之前最好先确认目标平台版本。关于“现代化”的美化我的建议是克制。流程图的第一要务是让路径关系清晰配色只用来标识“正常路径”“异常路径”或“不同模块”不要把整张图画成调色盘。我见过很多被过度美化的图反而分不清主干在哪。4.3 点击交互与多平台嵌入Mermaid 支持给节点绑定点击事件最常见的是跳转链接flowchart TD A[文档地址] -- B[接口文档] click A href https://example.com/docs _blank click B href https://example.com/api _blank鼠标悬停时还有tooltip提示语法是click A 提示文字。这个功能很适合在内部文档里做“流程节点 - 详细设计页”的关联读者不用离开页面就能跳转。嵌入方面我最常用的几个地方是GitHub / GitLab 的 README 和 Markdown 文件原生支持 Mermaid 渲染Typora 直接支持复制 Mermaid 代码块飞书文档需要插件或手动转换Hexo、Hugo、VuePress 这类博客框架通过插件或短代码支持Notion 原生不支持需要先渲染成图片再贴进去我的经验是凡是支持原生渲染的平台直接贴代码块还能利用代码搜索定位不支持的平台再考虑渲染成 SVG 或 PNG 导出这样至少保证源文件只有一个。5. 从流程图扩展出去柱状图、时序图与 BPMN 网关5.1 用 xychart-beta 画柱状图Mermaid 不只是画流程图的新版本提供了xychart-beta来画柱状图和折线图。这在不需要引入重量级图表库的场景下很方便。一个柱状图示例xychart-beta title 每月注册用户数 x-axis [1月, 2月, 3月, 4月, 5月] y-axis 人数 0 -- 1200 bar [320, 540, 780, 900, 1150]这段代码渲染出来就是一张带坐标轴、带标题的柱状图。同样语法可以换成line数据模式做成折线图。我提醒一句xychart-beta属于较新的语法部分平台的 Mermaid 版本较旧可能渲染失败。我在 GitHub 上遇到过老仓库里这个语法直接不显示的情况。使用前先确认渲染平台支持的版本或者用 Mermaid Live Editor 先把图生成好再嵌入文档。5.2 时序图表达系统交互比流程图更合适流程图适合描述“一个流程怎么走”但如果是多个角色之间的请求和响应时序图更合适。Mermaid 的sequenceDiagram语法也很简单sequenceDiagram participant user as 客户端 participant api as 后端服务 participant db as 数据库 user-api: POST /login activate api api-db: 查询用户信息 db--api: 返回用户记录 alt 密码正确 api--user: 返回Token else 密码错误 api--user: 返回401 end deactivate api这里-表示实线箭头消息--表示虚线返回消息activate和deactivate表示消息处理的生命周期alt/else表示分支场景。我的经验是跨系统接口设计文档里用一张时序图替代三段文字描述效果立竿见影。大家不需要读“客户端先调接口服务端再查库然后返回”这种话直接看图。时序图和流程图配合使用是文档里的黄金组合。5.3 BPMN 网关需要规范建模时的进阶选择搜索热词里“bpmn流程图网关使用”出现的频率不低。BPMN 的网关概念比普通流程图的判断复杂一些包括排他网关Exclusive Gateway、并行网关Parallel Gateway、包容网关等。Mermaid 在较新版本里加入了实验性质的bpmn模块bpmn task A task B task C但说实话这个模块目前还不稳定我在实际项目里很少用它。我的做法是在流程图里用{判断}菱形表达排他逻辑用普通并行分支表达并行网关视觉效果和 BPMN 类似但用的是成熟稳定的 flowchart 语法。如果团队严格要求 BPMN 规范建模我建议还是用专业的 BPMN 工具Mermaid 在这个领域仍未完全成熟。话又说回来熟练掌握 flowchart 的排他分支和并行拆分迁移到 BPMN 网关时思路是相通的。理解“排他网关是多个条件选一个并行网关是所有分支都执行”比纠结用哪个符号更重要。6. 画图三个月后我总结的避坑清单6.1 平台渲染不一致GitHub、Typora、Notion 的差异这是实际使用中最大的坑。同一份 Mermaid 代码在 GitHub、Typora、Mermaid Live Editor 里渲染结果可能不同。比如早些版本里graph和flowchart对边标签的处理有细微差别新语法如xychart-beta和老版本完全兼容不了。我踩过的具体案例在本地 Typora 里画了一个带flowchart LR的图效果正常推到 GitHub 之后发现子图内的方向变了。查了一圈是因为本地和 GitHub 用的 Mermaid 渲染版本不同导致部分语法的解析结果不同。现在我的策略是以 Mermaid Live Editor 为准写代码确认语法正确后再放进文档尽量使用稳定的基础语法涉及子图和主题变量时先在目标平台测试渲染团队文档规范中明确指定渲染平台和 Mermaid 版本6.2 长标签、中文与布局失控中文标签本身没问题但注意这些真实教训节点 ID 用英文显示文本用中文。这是保证大规模长流程图可维护的基石。连线文字里的中文换行用br/某些平台对\n转义支持不佳我这里吃过亏。标签特别长时图的宽度会被撑爆。解决办法有两个一是把长说明放到连线的 tooltip 或备注里二是把长标签拆分成多个短步骤节点。避免在一张图里混用过多的节点形状。形状是有语义的通篇全是菱形大小一样的判断块不如统一形状、用文字区分来得干净。另外如果你需要把“流程图转化为控制流图”或者做算法题分析布局失控会直接导致理解偏差。我的经验是先写伪代码再画 Mermaid 草图最后检查每一条边画出来的图通常结构清晰、分支紧凑。6.3 AI 生成流程图的协作方式前段时间我试过用 qwen-image 这类工具生成流程图也把生成结果和 ComfyUI 工作流做了结合测试。这类工具可以直接吐出 Mermaid 代码输出流程步骤、判断条件、异常分支都比较快适合用来快速起稿。但我的实际结论是AI 生成 Mermaid 代码可以大幅降低“从零开始”的启动成本但生成结果一定要人工 review。原因有两个。第一AI 生成的流程结构通常“过于合理”缺少真实业务里的边界情况。比如用户登录流程AI 一般会写“输入账号密码 - 验证 - 进入首页”但忘记画“账号被锁定”、“验证码过期”、“网络超时”这些分支。这些边界条件只有熟悉业务的人才能补上。第二AI 生成代码的节点 ID 往往是随机英文可读性差。你让 AI 生成用户管理模块图它可能给你 A、B、C 这种 ID下一步想改就麻烦了。我现在的做法是让 AI 先输出“流程大纲”也就是树状的步骤清单我确认逻辑无误后再让它基于清单生成 Mermaid 代码最后我统一改一遍节点 ID 和标签。如果你在做 renpy 这类文字冒险游戏也可以先用 Mermaid 画出剧情分支图确认好各个选项的分支关系再在 renpy 脚本里实现。这个流程我已经推荐给好几个做交互剧本的朋友了。结合 AI 工具时还有一个小技巧把 Mermaid 代码作为中间格式沟通成本会低很多。你不需要向 AI 解释“图里有个菱形代表判断”直接贴代码它能精准理解结构。这也是文本化图表最大的额外红利——人和机器都能顺畅消费。画了三五个月 Mermaid 之后我最深的一个体会是流程图的价值不在画图本身而在于逼你把逻辑理顺。用代码画图逼着我先把每个节点、每条边、每个判断条件都想清楚落笔只是最后一步。我也把这套习惯带进了团队新项目必须先产出“节点清单 连线清单”这两样东西再决定要不要画图。文档里凡是能用文字描述清楚的逻辑我都尽量留一份 Mermaid 源码在边上改起来是真的快乐。希望你也能早点体验到这种快乐并且别再为一张旧流程图被覆盖而捶桌子了。