资讯动态

离线环境下的Mermaid渲染:从Node安装到PNG/SVG导出全攻略

发布时间:2026/9/9 0:03:20 来源:尧图企业网站定制
有段时间我需要在完全隔离的内网环境里维护一份技术文档图形偏偏多得很。团队一直用Mermaid写流程图和时序图问题在于在线编辑器用不了平时那套mermaid-cli也没跑通最后只能在开发机渲染好再拷图来回折腾。等我把整套离线链路整明白发现从安装Node到导出PNG、SVG里头的坑比想象中多不少。这篇就按实操顺序捋一遍给同样被隔离环境卡住的人少走几步弯路。1. 离线使用场景和核心需求拆解1.1 先分清“离线”到底指什么很多人一上来就在找“Mermaid离线包”其实需求往往不一样。我归纳下来基本是四种第一种人在内网想要一个能渲染Mermaid的Web页面适合在浏览器里画图第二种文档里嵌了Mermaid代码块希望在本地Markdown工具或静态站点里正常出图第三种图表要作为图片插入Word、PPT或者提交到代码仓库必须渲染成PNG或SVG文件第四种开发阶段就要把Mermaid能力集成到内部系统里本地没网也能跑。这四种场景对应的方案完全不同。第一种可以用Live Editor的离线打包版本第二种靠支持Mermaid的本地编辑器第三种和第四种则几乎绕不开mermaid-cli。从热搜词里也能看出来“mermaid live editor”和“mermaid在线渲染”这种关注度一直很高但真正难倒人的是第三种——把Mermaid代码变成PNG和SVG文件而这个问题恰恰很多教程一笔带过。1.2 为什么会卡在PNG/SVG导出上W为什么偏偏倒出就卡住了根源在Mermaid的运行方式上。Mermaid本质是一段JavaScript库要在浏览器内核里渲染成图形。浏览器有但命令行没有所以要导图就得有一个“无头浏览器”参与绘制。mermaid-cli底层调用的正是Puppeteer而Puppeteer又要下载对应版本的Chromium。这一条链在联网机器上很顺畅在内网却每一步都可能断掉。这解释了为什么很多人明明装了mermaid-cli一执行mmdc就报各种错误最终都指向浏览器下载失败或启动不了。理解了这条原理后面的所有操作就有了方向离线环境下要解决Node安装、npm包离线导入、Chromium二进制准备三个问题三者缺一不可。这也是本文想重点展开的核心环节。2. 方案选型离线渲染Mermaid的几种可行路线2.1 从编辑器到命令行的完整路径对比要把Mermaid离线用起来方案不止一条。我实际摸过几种列个表对比一下方便按自己的场景选。方案适合场景导出PNG导出SVG离线友好度备注官方Live Editor离线版偶尔画一张不想写命令行手动截图支持直接下载中需从官网或已联网机器获取打包文件VS Code插件本地浏览器预览日常编辑文档协作不支持直接导出可复制代码中Markdown Preview Mermaid Support 类插件Typora个人笔记本地写文档复制图片复制SVG高图随文档走改代码要手动同步drawio嵌入Mermaid需要在线编辑已有图方便方便高本质是导到drawio再改跨工具折损mermaid-cli批处理、自动化、高精度输出支持支持低→可配置推荐用于正式输出图片的场景我自己最终留下的是mermaid-cli原因很实在能自动化、参数可控、出图质量稳定。其他方案适合轻量场景一旦图多了、要求统一风格、要跑在流水线里回到命令行几乎是必然选择。2.2 为什么大多数情况绕不开mermaid-cli假设你的文档里有20张Mermaid图手动一张张开页面渲染再截图精度和效率都很差。就算能下载SVGPNG的分辨率、背景色、缩放比例每个都不同完全没法统一。mermaid-cli则支持一条命令读入所有指定的.mmd文件批量出图还能通过参数统一图片尺寸、背景、缩放倍数对文档工程化是刚需。mermaid-cli导出的PNG背后其实是Chromium截屏不是矢量重绘所以它能保证所见即所得。SVG则是直接生成的矢量文件做印刷或者后续二次编辑都方便。这两类格式对应不同下游需求通常都需要所以命令行工具反而是最不容易被替代的路线。2.3 顺带评估drawio和Live Editor离线路线那是不是只用mermaid-cli就够了也不是。如果团队用了drawio本身支持通过Mermaid 插件让用户在图编辑器和文本语法之间切换这种交互体验是纯命令行给不了的。不过drawio的离线安装和Mermaid插件在隔离环境里部署又是一套依赖管理配置成本不一定低。官方Live Editor离线版则适合“临时用但不想装任何东西”的场景。把整个前端页面打包下载内网打开就能编辑渲染完成之后用浏览器自带功能存SVG或者用截图工具拿PNG。这种做法胜在零依赖不足是没有批量能力、截图像素不好控制。所以我的建议很直接只想画一两张用离线编辑器要正经产出图片直接学mmdc一次配置长期受益。3. 实操准备内网搭建Mermaid渲染工具链3.1 先解决运行时离线安装Node.jsmermaid-cli运行在Node环境里所以第一步是装Node。内网装Node和普通软件不太一样没法用nvm拉远程包好在官方提供了Windows、Linux、macOS的全平台二进制包。在能联网的机器上从Node官网下对应系统版本的tar.gz或.msi拷进内网解压即可。以Linux服务器为例例如拿到的包是node-v18.20.4-linux-x64.tar.xz放到/opt目录下解压后配置环境变量tar -xf node-v18.20.4-linux-x64.tar.xz -C /opt/ ln -s /opt/node-v18.20.4-linux-x64/bin/node /usr/local/bin/node ln -s /opt/node-v18.20.4-linux-x64/bin/npm /usr/local/bin/npm node -v npm -v解压版Node有个小坑npm会去找全局目录如果没有配置权限后面装包可能报EACCES。稳妥做法是给npm设置一个用户级目录或者直接用root执行、提前把~/.npm-global配置好。我第二次在内网部署时就是这样先踩了权限的坑。另外如果系统里有老版本Node建议选择Node 18或20这些LTS版本mermaid-cli的新版本对Node版本有要求太老跑不起来。3.2 在联网机器上准备完整的离线npm包离线安装npm包的核心思路是让npm把mermaid-cli及其全部依赖下载到一个缓存目录再把这个目录整个拷到内网。推荐用npm pack或者npm cache配合npm install --offline来做。个人更建议用npm cache方式因为依赖较多时更省心。在联网机器上执行mkdir /tmp/mmdc-offline cd /tmp/mmdc-offline npm init -y npm install mermaid-js/mermaid-cli此时node_modules已经生成npm缓存里也有了对应包。要精确控制版本可以指定版本号例如mermaid-js/mermaid-cli10.9.1避免联机和内网版本不一致导致找不到对应Puppeteer的坑。接下来把整个/tmp/mmdc-offline目录打包传到内网体积可能有几百MB因为里面有Chromium。这个体积正常不要觉得异常。另一种可行方法是先在有网机器上跑一次npm cache add 包名然后拷贝整个~/.npm/_cacache目录到内网对应位置再用npm install --offline安装。但实测下来直接拷贝带node_modules的项目目录更省事尤其对隔离环境更友好因为不用管缓存结构是否匹配。3.3 Chromium二进制缺失的终极处理方案把带node_modules的目录拷到内网后如果Puppeteer的默认浏览器路径没配好运行时仍会报“Could not find Chromium”。原因在于Puppeteer在安装时调用了puppeteer/browsers脚本去下载Chromium如果下载失败或路径被跳过缓存里没有可用浏览器。解决方案有两种。第一种简单粗暴在安装时设置环境变量PUPPETEER_SKIP_DOWNLOADtrue跳过下载然后单独找一台已经安装Chrome/Chromium的Windows或Linux机器把目录复制过去运行时通过--puppeteer-config指定路径。第二种更可控在联网机器上单独跑一次下载脚本缓存Chromium// download-chrome.js const { install } require(puppeteer/browsers); (async () { await install({ browser: chrome, buildId: stable, cacheDir: /tmp/chrome-cache, }); })();执行后把/tmp/chrome-cache整个带到内网运行时让Puppeteer读这个缓存目录。需要说明的是这种方式在国内网络环境下能否稳定下载依赖对象本身的连通性这里不展开但如果你在隔离程度高的环境最好提前验证一次是否有可用的外部下载条件若没有就把“拷目录”方案作为首选项。我在实际部署中用的是备用方案找内网一台已经装过Chrome的机器把chrome.exe所在路径记录下来用配置文件的方式让mermaid-cli直接走系统浏览器。这样省下了Chromium的下载和缓存问题稳定性也不错。3.4 用puppeteer-config文件管理浏览器路径mermaid-cli支持通过一份JSON配置文件指定Puppeteer的选项这是离线环境的标配操作。在项目目录里新建puppeteer-config.json内容如下{ executablePath: /opt/chrome/chrome, args: [--no-sandbox, --disable-setuid-sandbox] }其中--no-sandbox主要在Linux服务器上跑时有帮助。平时我不建议root用户跑无头浏览器时不加这个参数实际碰到过默认沙箱权限不足导致白屏的案例。这一配置需要在执行mmdc时用-p参数指向./node_modules/.bin/mmdc -p puppeteer-config.json -i input.mmd -o output.png配置好这一步才算把离线的最后一个堵点打通了。之后所有导图操作都能正常跑通体验和联网环境差别不大。4. 从Mermaid代码到PNG、SVG的完整导出实操4.1 准备一份可用的测试图例和基础命令先用一个最简单可复现的例子入门。新建文件test.mmd内容如下graph TD A[需求收集] -- B[方案设计] B -- C{评审通过?} C --|否| B C --|是| D[开发实现] D -- E[测试验证] E -- F[上线发布]这是最基础的代码实际上扩展成任意类型的flowchart、sequenceDiagram或gantt都适用不过第一次测试最好用简单图便于排错。此时执行导出命令./node_modules/.bin/mmdc -i test.mmd -o test.png ./node_modules/.bin/mmdc -i test.mmd -o test.svg如果工具链配置正常目录下会生成两个文件。PNG默认是96dpi左右对于屏幕显示足够要用于印刷或者PPT全屏展示建议提高输出分辨率。4.2 导出一张高质量PNG的关键参数PNG导出的核心是控制分辨率、缩放、背景、宽度。我第一次接触时以为图片尺寸由-w直接决定其实-w控制的是最终输出的图片宽度和真实可用尺寸有关。还有-s这个缩放因子mermaid-cli官方定义为缩放系数3表示300%即放大三倍渲染但不改变逻辑尺寸。实践中最常用的组合是这样./node_modules/.bin/mmdc -i test.mmd -o test.png -s 3 -b white -w 1200其中-b设置背景色默认是white但很多场景要透明背景就设为transparent比如把图贴到深色PPT或网页里。-w会把生成的图片按宽度约束重新缩放搭配-s用的时候注意两者不要同时控制同一维度容易产生期望外的分辨率。通常做法是只设-s 2或-s 3不做-w限制让图片保持原始宽高比兼容性更好。有次我为了把图片压到800px宽直接加了-w 800结果导出后文字也被拉伸模糊后来改为靠缩放因子控制才得到清晰且尺寸合理的图。其实可以这样理解mermaid渲染时先在内存里按96dpi生成位图-s控制内存位图的放大倍数相当于超采样抗锯齿数值越高文字边缘越平滑同时PNG文件自然变大。建议在2到4之间调试太高的倍数对复杂图收益不大。4.3 SVG导出的细节与后续处理方法导出SVG则相对简单./node_modules/.bin/mmdc -i test.mmd -o test.svgSVG是矢量文件不需要设置分辨率。它的问题更多在后期使用环节。Mermaid生成的SVG里会带一些引用的CSS类和字体信息直接用浏览器打开一般正常但如果用Illustrator等工具打开可能出现文字偏移或字体缺失。我在导入Visio时就遇到过一次后面通过调整SVG中引用的字体族为通用字体族解决。另外SVG文件中如果存在中文要确保渲染环境里有中文字体。否则Chromium会按字体回退逻辑用一种没注册的字体代替最终导出的SVG在自己机器上看着正常换到没有对应字体的机器就乱。处理方式是在配置文件中指定字体路径或者统一用系统常用中文字体如Microsoft YaHei、Noto Sans CJK SC。如果团队文档是跨平台全阅读尽可能在流程图里少用特殊字符常规汉字一般没事。4.4 批量导出几十张图的自动化脚本当图数量多起来手敲命令不合适。我会把图放在./diagrams目录里写一个脚本遍历处理#!/bin/bash set -e for mmd_file in diagrams/*.mmd; do base_name$(basename $mmd_file .mmd) echo processing $base_name ... ./node_modules/.bin/mmdc -p puppeteer-config.json -i $mmd_file -o output/${base_name}.png -s 3 -b transparent ./node_modules/.bin/mmdc -p puppeteer-config.json -i $mmd_file -o output/${base_name}.svg done在Windows下可以写等价的PowerShell脚本思路一致。执行前保证output目录存在否则导出会失败。这里有个实用经验脚本里加上--failOnError如果某张图语法有误命令会直接返回非0状态在CI里能够中断构建避免产出半成品没人发现。5. 高频问题排查与避坑实录5.1 经典错误找不到Chromium或沙箱报错这是离线环境遇到最多的一个问题。报错信息格式多为“Could not find Chrome”、“Failed to launch the browser process”或“SUID sandbox helper not found”。处理方式按三步排查第一步确认为mermaid-cli提供的Puppeteer配置文件路径被正确传递第二步确认配置文件中的executablePath指向的内置浏览器可执行文件真实存在且有执行权限第三步在Linux上确保添加了--no-sandbox参数。从我个人经验看第一次跑不起来八成是executablePath写错了或路径下没有可执行文件。可以先手动执行一次ls -l /opt/chrome/chrome验证一下而不是盲目改参数。5.2 导出的图片中文变成方块或缺失中文字体缺失是最影响观感的问题尤其在服务器端导出。Linux服务器默认通常没有Windows下的宋体或微软雅黑渲染时只能fallback结果往往是方块。最直接的解决办法是在服务器上安装中文字体apt-get install fonts-noto-cjk或者将Windows系统的msyh.ttc复制到Linux的/usr/share/fonts目录执行fc-cache -f刷新字体缓存。如果你的容器是精简版可能没有fontconfig命令需要一并安装。装好后重新跑一次导出中文基本就正常了。5.3 Mermaid语法对HTML标签的支持差异Mermaid图里经常用br/换行或加粗标签这些在在线编辑器里没问题但mermaid-cli不同版本对HTML标签处理有差异。特别是flowchart节点里用b标签时部分版本会解析成实体文本而不是标签导致显示错乱。规避办法是优先使用Mermaid自身的换行语法例如在节点文本中使用br/已经是官方示例但更稳妥的办法是少在经典语法里依赖HTML渲染能力该用sequenceDiagram中的br/时留意不同版本的表现。如果只是给节点文本换行用br/倒是通用但如果要加颜色、背景这类富文本样式推荐改用其他标记方式或者干脆在SVG输出后用编辑器工具二次加样式因为mermaid的富文本能力真的不是设计来承接复杂HTML的。5.4 同一套图在不同环境渲染结果不同这个问题发生频率不低我在交接项目时碰到过几次。原因是mermaid版本不同、主题变量不同、字体不同。为了保持结果稳定建议在项目里固定mermaid版本做法是在package.json中锁定mermaid-js/mermaid-cli的具体版本号并统一使用某种主题例如-t default、-t dark、-t forest避免使用默认主题但依赖了某次版本更新带来的样式变化。如果对内网出口受限注意命令行工具可能每个季度升一次级不要频繁更新更新一次就要重新做一遍完整的离线同步。我自己通常锁一个版本批量生成图时完全不改动环境确保可重复性。5.5 问题排查速查表把上面几个高频坑整理成一张表方便现场排查现象可能原因快速处理执行mmdc报找不到浏览器Puppeteer配置路径错误或没有Chromium检查puppeteer-config.json的可执行路径图渲染出来全空白沙箱权限问题加--no-sandbox参数PNG图片文字模糊缩放因子过低将-s设为2或3中文变方块缺少中文字体安装fonts-noto-cjk与在线编辑器渲染效果不同Mermaid版本或主题不一致固定版本和主题批量命令中途停止单张图语法错误排查对应.mmd文件语法6. 基于个人实践的经验沉淀把这套链路完整跑通之后我在多个项目里都采用了同样的模式给文档库配置好mermaid-cli环境所有图形文件都以.mmd文本形式维护然后通过脚本统一导出PNG和SVG。这比手动改图、重新截图高效很多也方便做版本管理代码评审时可以直接看.mmd文件的差异。最后提一个实用习惯在源文件头部统一写清楚图的类型和主题。例如%%{init: {theme:base, themeVariables: {primaryColor: #d9e8fb}}}%% graph LR A[模块A] -- B[模块B]这一段init配置能让团队作图风格统一也能让导出环境更可控。我之前踩过几次版本不同导致主题色不对的坑固定init之后省了很多麻烦。Mermaid离线这件事说难是真繁琐理顺后又觉得是固定套路先装Node和依赖再配好Chromium路径导出就是一行命令的事。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价