Lazy-Loading Mermaid Preserves Bundle While Enabling Rich Diagrams
The Dilemma
We needed to render Mermaid diagrams inline in the Knowledge detail page and diff view. But Mermaid is 50KB gzipped — a significant addition to our Next.js bundle. Options considered:- Import globally — adds 50KB to every page (bad)
- Lazy import in component — works, but duplicated across 3 places (wasteful)
- Shared MermaidRenderer component + lazy import inside — optimal
The Implementation
Single Shared Component
Used in Multiple Places
Bundle Impact
Measurement
- Initial bundle (without Mermaid): 128 kB gzipped
- With global import: 128 + 50 = 178 kB (39% bloat)
- With lazy import via shared component: 128 + 1 = 129 kB
- Mermaid loaded only when first diagram renders
- Shared component prevents duplication
Results
Why This Works
1. Lazy Import Only on First Render
import() statement doesn’t load the module until called. First diagram triggers the fetch.
2. Single Component Prevents Duplication
If 3 pages each had their own lazy import:3. Async Loading Doesn’t Block Page
Performance Characteristics
Initial Page Load (no diagrams)
- Time to First Contentful Paint (FCP): Unaffected
- Mermaid not loaded
First Diagram Rendered
- Mermaid library fetched (50KB, ~200ms on 4G)
- Async render (doesn’t block interactions)
- Diagram appears in ~300ms total
Subsequent Diagrams
- Mermaid already cached in memory
- Render happens instantly (~50ms per diagram)
Error Handling Strategy
Graceful Degradation
Validation Before Render
Cancellation Prevents Memory Leaks
Real-World Impact: BLOCK 21
Knowledge Detail Page
- 5–10 diagram CIs per baseline
- First diagram triggers Mermaid load (~300ms)
- Subsequent diagrams instant
- Users see content immediately, diagrams load progressively
Diff View
- Side-by-side comparison (2 diagrams at once)
- Mermaid already cached from detail page
- No additional bundle load
- Responsive layout: desktop side-by-side, mobile stacked
Comparison with Alternatives
Alternative 1: Server-Side Render (SSR)
- Generate SVG on server, send to client
- Pros: No JS needed, instant rendering
- Cons: Server CPU cost, inflexible (can’t switch themes client-side)
Alternative 2: Canvas/WebGL Renderer
- Use custom renderer instead of Mermaid
- Pros: Smaller bundle
- Cons: Maintenance burden, fewer diagram types supported
Alternative 3: External Diagram Service
- Call API to render diagrams
- Pros: Offload to specialized service
- Cons: Network latency, privacy concern (diagrams sent to external service)
- Minimal bundle bloat (only 50KB)
- Client-side rendering (responsive to theme changes)
- No external dependencies
- User doesn’t wait (async load after render)
Operational Recommendations
When to Use Mermaid
- Flowcharts, sequences, state diagrams (10–100 nodes)
- Real-time editing (update syntax, see diagram immediately)
- Multi-diagram pages (5–20 per page)
When NOT to Use
- Extremely complex diagrams (1000+ nodes) — consider static images
- Performance-critical pages — pre-render as images
- Accessibility requirements — Mermaid output needs alt-text generation
Bundle Monitoring
Add to CI/CD:Metrics from BLOCK 21
| Metric | Value |
|---|---|
| Initial bundle (without diagrams) | 128 kB gzipped |
| Mermaid lazy loaded size | +50 kB (only on first diagram) |
| Time to render first diagram | ~300ms (includes fetch) |
| Time to render 2nd+ diagrams | ~50ms each (cached) |
| Bundle bloat (shared component) | +0.8% |
| Number of diagram CIs per baseline | 5–10 |
| Pages using MermaidRenderer | 3 (detail, diff, editor) |
Next Steps
Optimizations
- Cache rendered SVGs — Store SVG output, skip re-render on same syntax
- Intersection Observer — Don’t render off-screen diagrams
- Web Worker — Offload rendering to separate thread
Monitoring
- Track Mermaid load latency in production
- Alert if bundle size regresses
- Monitor diagram render errors (syntax issues)
Learnings
- Lazy import is free — Don’t pay 50KB upfront for optional feature
- Shared component prevents duplication — One lazy import, many uses
- Async rendering improves perceived performance — Load diagram after page is interactive
- Error boundaries isolate failures — Bad diagram syntax doesn’t crash app
- Cancellation tokens prevent memory leaks — Essential for async effects
Related Reading:
SKILL-mermaid-diagram-rendering.md for detailed implementation patterns, theme integration, export functionality, and performance optimizations.