Rendering Mermaid diagrams: options and trade-offs
On this page
Mermaid lets you write a diagram as text and keep it next to the text it explains. But Mermaid lays out diagrams by measuring text in a real browser. A static site has three ways to deal with that.
The three options
| Option | When it draws | JS sent to readers | Build needs | Dark mode |
|---|---|---|---|---|
| Draw in the browser | On page load | ~650 KB minified (~165 KB gzipped), only on diagram pages | Nothing | Re-draw with a dark theme |
Draw at build time (rehype-mermaid) |
During the build | None | Headless Chromium (Playwright) | Two SVGs per diagram |
Pre-render by hand (mermaid-cli) |
When you run it | None | Nothing for the site build; Chromium on your machine | Two SVGs per diagram |
1. Draw in the browser
Leave the Mermaid source in the HTML and let a script turn it into SVG.
- Pros: No build dependencies. Writing a diagram means writing a code block, nothing more. Diagrams can re-draw when the reader switches colour scheme.
- Cons: Mermaid is large, and each diagram type adds its own code on top, usually 20–120 KB. The diagram appears a moment after the page loads. Readers without JavaScript see the source text.
2. Draw at build time
The rehype-mermaid plugin starts a headless browser during the build and swaps each block for an inline SVG. Astro 7 turns Markdown into HTML with Sätteri, which doesn’t run rehype plugins, so you must first switch to the unified() processor (@astrojs/markdown-remark).
- Pros: No JavaScript for readers; diagrams appear instantly.
- Cons: Every build (local, CI, and Vercel) must download and run Chromium. Builds get slower and more fragile, and dark mode needs a second SVG per diagram.
3. Pre-render by hand
Run mermaid-cli yourself and commit the SVG files.
- Pros: No JavaScript for readers, and the site build needs nothing extra. Your own machine still needs Chromium, which
mermaid-clidownloads through Puppeteer. - Cons: The source and the image live apart and drift. Every edit needs a manual export.
What this blog does
This blog draws diagrams in the browser, but only on pages that contain one. The build marks each mermaid block so the code highlighter skips it; a small script then loads Mermaid on demand:
flowchart LR
A[MDX file] --> B{mermaid block?}
B -- yes --> C["pre.mermaid (left as text)"]
B -- no --> D[Syntax highlighter colours it]
C --> E[Browser loads Mermaid on demand]
E --> F[SVG diagram]
Here is what happens when you open this page:
sequenceDiagram actor R as Reader participant B as Browser participant S as Web server R->>B: Open the post B->>S: Get the page S-->>B: HTML and a small page script B->>B: Script finds a pre.mermaid block B->>S: Get Mermaid files (only on diagram pages) S-->>B: Mermaid code B->>R: Show the diagram in light or dark theme R->>B: Switch OS to dark mode B->>R: Re-draw in dark theme
Pages without diagrams load none of this.
If a diagram page feels slow, pre-render that one diagram with mermaid-cli; the others can keep drawing in the browser.