tech-book-labs
可視化(チャート / 図 / 表) · 最終検証 2026-05-26 · beautiful-mermaid 1.1.3 · 初公開 2026-05-09

beautiful-mermaid でゼロ依存の Mermaid 図を描く

ゼロ依存・DOM 非依存の beautiful-mermaid を Astro + MDX に組み込み、build 時の静的レンダリングと runtime のインタラクティブエディタを共存させた実装メモ。renderMermaidSVG が同期で SVG 文字列を返す設計、公式 mermaid との機能差、50 ノード超で build が伸びる閾値まで。

mermaid mdx astro diagram

検証日: 2026-05-26

使用バージョン: beautiful-mermaid@1.1.3(2026-05 時点で main)

環境: Node 22.12 / Astro 6.3 / MDX 5

技術記事に を入れたい場面はよくあるが、Mermaid 公式ライブラリ(mermaid)は重く、DOM 依存があるためサーバーサイドでの静的 SVG 生成が大変。 beautiful-mermaidゼロ依存・DOM 非依存 で SVG を同期 render できるので、Astro の build 時にそのまま図に変換できる。

利用形態は 2 つ:

  1. 静的に埋め込む(<Mermaid /> Astro コンポーネント、build 時 SVG)
  2. 触れるエディタ(<MermaidEditor /> React コンポーネント、runtime 編集 + 即時再描画)

セットアップ(npm 1 行 / Node / Browser / Deno / Bun)

npm i beautiful-mermaid
項目
公開バージョン1.1.3(2026-05)
Node 必要バージョン18+
TypeScript 型本体同梱
依存ライブラリ0(他の npm パッケージを引きずらない)
DOM 依存なし(jsdom / canvas 不要、純粋関数として SVG 文字列を返す)
ライセンスMIT

公式 mermaid パッケージは DOM 依存があり、Node 上で SSR したい時は jsdom 経由で重い初期化が必要。beautiful-mermaidrenderMermaidSVG(code)同期関数で SVG 文字列を返す ので、Astro の set:html にそのまま流せる。

import { renderMermaidSVG } from "beautiful-mermaid";

const svg: string = renderMermaidSVG("graph TD\nA-->B");
// → "<svg xmlns=...>...</svg>"

公式 mermaid との機能差(2026-05 時点)

機能公式 mermaidbeautiful-mermaid v1
flowchart / graph
sequenceDiagram
classDiagram
erDiagram
stateDiagram△(限定的)
gantt
mindmap
journey
%%{init: ...}%% テーマ❌(v1 では未対応)
同期 SVG 生成❌(非同期 + DOM 必要)✅(同期、DOM 不要)
DOM 依存ありなし
依存パッケージ数数十(d3 / dagre 等)0

「記事に flowchart / sequence / ER を埋めたい」用途は beautiful-mermaid が圧倒的にラク(SSR で SVG 焼ける、初回描画ゼロ wait)。「gantt / mindmap / theme カスタマイズが必要」なら公式 mermaid を browser ロードする。

静的埋め込み 1 — Astro コンポーネント(build 時 SVG)

<Mermaid code={...} /> を MDX から呼ぶだけで、build 時に SVG が埋め込まれる。

記事執筆の流れ(static SVG) (クリックで拡大)

シーケンス図も同じインタフェース。

同期 API リクエストの流れ (クリックで拡大)

触れる Mermaid エディタ

プリセットからテンプレートを選んで編集してみてください。左を変えると右が即座に再描画されます。

プリセット:
ライブエディタ — 左を編集すると右が即座に再描画されます。レンダラはbeautiful-mermaid(ゼロ依存、build/ runtime 両対応)。

実装の中身

Astro コンポーネント(static)

サーバー側で renderMermaidSVG(code) を呼んで、結果の SVG 文字列を set:html で埋め込むだけ:

---
import { renderMermaidSVG } from "beautiful-mermaid";

interface Props {
  code: string;
  caption?: string;
  maxWidth?: string;
}
const { code, caption, maxWidth = "100%" } = Astro.props;

let svg = "";
let error: string | null = null;
try {
  svg = renderMermaidSVG(code);
} catch (e) {
  error = (e as Error).message ?? "Mermaid render error";
}
---

<figure class="not-prose my-6">
  <div class="overflow-x-auto p-4 border border-line rounded-lg" style={`max-width: ${maxWidth}`}>
    {error ? <pre>{error}</pre> : <div set:html={svg} />}
  </div>
  {caption && <figcaption>{caption}</figcaption>}
</figure>

React コンポーネント(interactive)

ブラウザでも renderMermaidSVG が動くので、useMemo で code → SVG を再計算する interactive editor が組める:

import { useEffect, useMemo, useRef, useState } from "react";
import { renderMermaidSVG } from "beautiful-mermaid";

export function MermaidEditor({ initialCode }: { initialCode?: string }) {
  const [code, setCode] = useState(initialCode ?? PRESETS[0].code);

  const svg = useMemo(() => {
    try {
      return renderMermaidSVG(code);
    } catch (e) {
      return "";
    }
  }, [code]);

  // ...textarea + preview の 2 列 layout
}

useMemocode が変わるたびに再 render。beautiful-mermaid は同期 + ゼロ依存なので、setState の度に呼んでも安定して動く。

表示の調整(向き / サイズ / 余白)

ある程度のスタイル調整は Mermaid コード自体のディレクティブ で済む。

方向(graph LR vs graph TD)

TD = Top-Down、LR = Left-Right。横に長い図は LR が読みやすい。

LR 方向(横長) (クリックで拡大)

Subgraph(クラスタリング)

関連ノードをグルーピングして見せたい時は subgraph

public / private の境界を subgraph で可視化 (クリックで拡大)

サイズ調整(maxWidth prop)

<Mermaid maxWidth="480px" /> で図の最大幅を絞れる(コンテナに pad されて中央揃え)。 小さく見せたい補足図に有効。

エラーハンドリング — 不正な構文を入れた時

renderMermaidSVG は構文エラーで例外を投げる(空文字列ではない)。Astro 側で try/catch し、error を fallback として <pre> で表示するのが安全:

---
import { renderMermaidSVG } from "beautiful-mermaid";

const { code } = Astro.props;
let svg = "";
let error: string | null = null;
try {
  svg = renderMermaidSVG(code);
} catch (e) {
  error = (e as Error).message;
  // build を停止させたくない場合は console.warn のみで継続
}
---

{error ? <pre>{error}</pre> : <div set:html={svg} />}

MermaidEditor(React)側でも useMemo の中で try/catch しないと、入力ミスのたびに React tree 全体が unmount される。

5 つの落とし穴と直し方

症状原因直し方
MDX 内の複数行 Mermaid コードで改行が壊れる文字列リテラルが "..." の途中で切れるcode={\graph TD\nA—>B`}` のように template literal で渡す
<ISBN> のような < が消えるMDX が tag と解釈label 内で < を使わない、もしくは &lt; を埋めるか template literal で escape
theme を変えたいv1 系は %%{init: ...}%% 未対応CSS 変数で color-mermaid-line を上書き、もしくは出力 SVG を後処理
gantt / mindmap が描けないv1 系で 未サポート公式 mermaid を browser ロード、または別ライブラリ(@nivo、d3)で代替
50 ノード超の図で build が伸びる1 図あたり ~100ms 程度かかる1 図 5-15 ノード × 図 10 個 を上限目安。重い図は画像化(svg を SVG ファイルに書き出して <img> 参照)

評価

観点評価コメント
学習コストAPI は render(code, { format }) の 1 つだけ
依存ゼロ依存(npm install で他に何も入らない)
環境互換性Node / browser / Deno / Bun いずれも動く
ダイアグラム種別flowchart / sequence / class / ER は OK、gantt / mindmap は限定的
カスタマイズテーマやフォントの細かい調整は v1 系では限定的

向く / 向かないケース

  • 向く: 技術記事 / ドキュメントへの図埋め込み(flowchart / sequence / class / ER 中心)、サーバーサイド SVG 生成、AI agent の図出力
  • 向かない: gantt や複雑な mindmap が必要な場面 → 公式 mermaid を browser ロード
  • 向かない: テーマ / 色 / フォントの厳密なブランド統制が必要な場面 → SVG を後処理するか、別のダイアグラムライブラリを検討

関連 Topic / 関連書籍

この記事と関係する tech-book.net の Topic と、それぞれの Topic に紐づく書籍:

tech-book.net /books/9784814401093

Effective TypeScript(第2版) : 型システムの力を最大限に引き出す83項目 | tech-book.net

Dan Vanderkam/今村 謙士

関連テーマ・学習ロードマップから次の一冊へ。

詳細を tech-book.net で見る
tech-book.net /books/9784297129163

TypeScriptとReact/Next.jsでつくる実践Webアプリケーション開発 | tech-book.net

手島 拓也/吉田 健人/高林 佳稀

関連テーマ・学習ロードマップから次の一冊へ。

詳細を tech-book.net で見る
tech-book.net /books/9784297137397

かんたん TypeScript | tech-book.net

HIRO

関連テーマ・学習ロードマップから次の一冊へ。

詳細を tech-book.net で見る
tech-book.net /books/9784297126353

ゼロからわかる TypeScript入門 | tech-book.net

WINGSプロジェクト 齊藤新三/山田 祥寛

関連テーマ・学習ロードマップから次の一冊へ。

詳細を tech-book.net で見る
tech-book.net /books/9784297127473

プロを目指す人のためのTypeScript入門 安全なコードの書き方から高度な型の使い方まで | tech-book.net

鈴木 僚太

関連テーマ・学習ロードマップから次の一冊へ。

詳細を tech-book.net で見る