Zhi主题使用一月记:Mermaid v11升级实战体验

使用一月

距离上一篇 《给博客换了个主题:从 Hugo NexT 到自写的 Zhi》 文章已经快一个月了。这一个月里,主题一直在稳定运行,没有出现重大问题。NexT 主题的替换是正确的决定,虽然初期有点适应,但现在的体验确实好很多。

一个月使用下来,主题的稳定性超出预期。当初的顾虑——没有构建工具、纯 Hugo Pipes 能否支持复杂需求——都被事实打脸了。日常维护变得很简单,要改功能不用再翻层层嵌套的 SCSS 文件,一个 CSS 文件搞定。

但说实话,这一个月也不是完全风平浪静。遇到的问题集中在几个地方,其中最明显的是 Mermaid 的使用体验。

为什么升级到 v11

用 Zhi 主题写了三四篇文章,发现 Mermaid v10 的局限性越来越明显。问题主要集中在几件事上:

基本形状太少。v10 只提供 [rect]{diamond}(rounded)[(cylinder)]((circle)) 这几种基本形状,画稍微复杂一点的架构图就捉襟见肘。想要画个文档图标、六边形、或者梯形,要么用文字替代,要么就得用复杂的代码模拟。

样式控制弱。v10 几乎没有样式定制能力,节点只能通过文本内容改变,颜色、边框、字体大小这些基础样式都得靠手动添加 CSS。深色模式下的 Mermaid 图表总是看起来不太协调。

新图表类型不支持。v11 引入了很多新的图表类型,比如 architecture(架构图)、kanban(看板图),这些在 v10 中根本不存在。对于技术博客来说,这些新图表类型的实用性很高。

性能问题。v10 的初始化方式比较老套,用的是 mermaid.initialize({startOnLoad:true}) 这种阻塞式加载,页面加载时会有明显的卡顿。

综合这些考虑,决定升级到 Mermaid v11。

技术变化

main.js 重写

升级的核心在 main.jsinitMermaid() 函数。原来的 v10 代码很简单:

javascript
1
mermaid.initialize({startOnLoad: true});

v11 改成了 async/await 异步加载模式:

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
async function initMermaid() {
    var hasMermaidCode = document.querySelector('code.language-mermaid, pre.mermaid');
    if (!hasMermaidCode || !window.mermaid) return;

    var isDark = document.querySelector('[data-theme="dark"]');
    await window.mermaid.initialize({
        startOnLoad: false,
        securityLevel: 'loose',
        theme: 'base',
        themeVariables: isDark ? darkThemeVars : lightThemeVars
    });

    // 处理代码块,替换为 pre 标签
    document.querySelectorAll('code.language-mermaid').forEach(function(block) {
        var pre = document.createElement('pre');
        pre.className = 'mermaid';
        pre.textContent = block.textContent;
        var wrapper = block.closest('.code-block-wrapper');
        if (wrapper) { wrapper.replaceWith(pre); }
        else { block.replaceWith(pre); }
    });

    await window.mermaid.run();
}

主要变化:

  1. 从同步初始化改为异步 async/await
  2. 只有检测到 Mermaid 代码块时才加载和初始化
  3. 支持暗色/亮色主题的 themeVariables 动态切换
  4. 主题设置从 default 改为 base,配合自定义 themeVariables

CDN 变更

mermaid.html 模板中的 CDN 链接也从版本号固定改为无版本号:

html
1
2
3
4
5
<!-- v10 版本固定 -->
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>

<!-- v11 无版本号 -->
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>

这样永远使用最新版本,及时获取新功能和 bug 修复。

v11 vs v10 功能对比

节点形状扩展

v10 基本形状

  • [rect] 矩形
  • {diamond} 菱形
  • (rounded) 圆角矩形
  • [(cylinder)] 圆柱形
  • ((circle)) 圆形

v11 扩展形状

  • @{ shape: doc } 文档图标
  • @{ shape: cyl } 圆柱形
  • @{ shape: diam } 菱形
  • @{ shape: hex } 六边形
  • @{ shape: stadium } 体育场形
  • @{ shape: rounded } 圆角矩形
  • @{ shape: trapezoid } 梯形
  • @{ shape: double-circle } 双圆
  • @{ shape: circle } 圆形

样式控制

v10 几乎没有样式控制能力,只能通过文本内容来区分节点。

v11 引入了 classDefclass

yaml
1
2
3
classDef primary fill:#e1f5fe,stroke:#0288d1
classDef warn fill:#fff3e0,stroke:#ef6c00
classDef storage fill:#e8f5e9,stroke:#4caf50

然后给节点分配样式:

mermaid
graph TD
    A@{ shape: doc, label: "Document" } --> B@{ shape: diam, label: "Decision" }
    B -->|Yes| C@{ shape: hex, label: "Process" }
    B -->|No| D@{ shape: cyl, label: "Database" }
    
    class A,C primary
    class B warn
    class D storage

新图表类型

v11 新增支持

  • architecture (v11.1+) - 架构图,专门用于系统架构设计
  • kanban (v11.0+) - 看板图,适合项目管理展示
  • timeline 改进 - 更好的时间线样式控制
  • gitgraph - Git 分支图增强

布局引擎

v11 支持 ELK 布局引擎,对于复杂图表的自动布局效果更好:

yaml
1
2
3
4
5
6
7
%%{init: {'theme': 'base', 'themeVariables': {}}}%%

graph TD
    A@{ shape: doc, label: "前端应用" } --> B@{ shape: diam, label: "负载均衡" }
    B --> C@{ shape: cyl, label: "应用服务器" }
    C --> D@{ shape: cyl, label: "数据库" }
    C --> E@{ shape: cyl, label: "缓存" }

序列图增强

v11 支持矩形背景,这在 v10 中是没有的:

mermaid
sequenceDiagram
    participant C as 客户端
    participant S as 服务器
    
    rect rgba(76,175,80,0.1)
        Note over C,S: 认证过程
        C->>S: login(username, password)
        S->>S: 验证用户信息
        S->>C: auth_token
    end
    
    Note over C: 使用 token
    C->>S: api_call(auth_token)

主题变量定制

v11 通过 themeVariables 全面控制样式

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
var lightThemeVars = {
    background: '#FAFAFA',
    primaryColor: '#EDE9F6',
    primaryBorderColor: '#D5CFF0',
    primaryTextColor: '#1A1A2E',
    // ... 更多变量
};

var darkThemeVars = {
    background: '#1e1e2e',
    primaryColor: '#313244',
    primaryBorderColor: '#45475a',
    primaryTextColor: '#cdd6f4',
    // ... 更多变量
};

实际效果对比

v10 风格的图表

mermaid
graph LR
    A[用户请求] --> B{Nginx}
    B -->|静态资源| C[CDN]
    B -->|API 调用| D[Go 服务]
    D --> E[(PostgreSQL)]
    D --> F[(Redis)]
    C --> G[用户浏览器]

问题:形状单一、样式单调、缺乏层次感。

v11 风格的图表

mermaid
graph TD
    subgraph Collect[采集层]
        A1@{ shape: doc, label: "Prometheus Agent 1" }
        A2@{ shape: doc, label: "Prometheus Agent 2" }
    end

    subgraph VMAgent[vmagent 集群]
        B1@{ shape: hex, label: "vmagent-0" }
        B2@{ shape: hex, label: "vmagent-1" }
    end

    subgraph Storage[存储层]
        D1@{ shape: cyl, label: "vmstorage-0" }
        D2@{ shape: cyl, label: "vmstorage-1" }
    end

    A1 --> B1
    A2 --> B2
    B1 --> D1
    B2 --> D2

    classDef storage fill:#e8f5e9,stroke:#4caf50
    classDef compute fill:#e3f2fd,stroke:#2196f3
    class D1,D2 storage
    class B1,B2 compute

优势:形状丰富、样式分层、结构清晰、视觉效果好。

主题集成

暗色/亮色切换时,v11 的重新渲染机制比 v10 好很多。v10 中切换主题后 Mermaid 图表不会自动更新,需要刷新页面。

v11 的实现很巧妙:

  1. 点击主题切换时,给所有 Mermaid 容器添加 re-rendering
  2. 200ms 后重新初始化 Mermaid,使用新的 themeVariables
  3. 清除容器的 data-processed 属性
  4. 重新注入图表内容
  5. 执行 mermaid.run() 渲染新主题的图表
  6. 移除 re-rendering

这个机制确保了主题切换时图表能平滑过渡。

升级过程

实际的升级过程比预想的简单。主要修改了两个文件:

  1. mermaid.html - CDN 链接更新
  2. main.js - initMermaid() 函数重写

代码量不大,但调试花了一些时间。主要问题是:

  • async/await 的错误处理需要完善
  • 主题变量的暗色模式配色需要反复调整
  • 重新渲染的延迟时间需要测试确定

整个升级过程大概花了半天时间,大部分时间花在调试和样式优化上。

发布和部署

这次升级随着 Zhi 主题的 v0.1.0 版本一起发布。GitHub Actions 的 CI/CD 工作流在打 tag 时自动触发:

yaml
1
2
3
4
5
name: Release
on:
  push:
    tags:
      - 'v*'

构建、测试、打包、发布一条龙完成。第一次使用 GitHub Releases 功能,体验比预想的好。

AI 的角色

这次升级过程中,AI 扮演了重要角色。主要是:

  1. API 文档查询 - 查询 Mermaid v11 的官方文档,了解新功能
  2. 代码生成 - 根据 v11 API 重写了 initMermaid() 函数
  3. 调试辅助 - 帮助排查 async/await 的异步加载问题
  4. 样式优化 - 提供了 themeVariables 的配色方案建议

特别值得一提的是,在处理主题切换时的重新渲染逻辑时,AI 的建议很有价值。第一次尝试时直接调用 mermaid.initialize() 会导致内存泄漏,AI 提供的解决方案是通过清除 data-processed 属性来实现正确的重渲染。

总结

从 Mermaid v10 升级到 v11 是值得的。新功能确实带来更好的图表体验,特别是:

形状扩展让图表更生动,不再受限于基本图形 样式控制让图表有层次感,技术文档的专业度提升 新图表类型拓展了使用场景 异步加载改善了页面性能 主题适配让暗色模式体验完美

虽然升级过程有一些技术细节需要处理,但总体来说是成功的体验。Zhi 主题在 Mermaid v11 支持上已经相当完善,能够满足大部分技术博客的图表需求。

其实还有其他可以升级的地方,比如 MathJax 的新版本、更好的代码高亮样式等。但这些可以留到下次迭代再说。现在的状态已经很稳定,先这样用着吧。