Embedding PlantUML in Hexo (server vs client rendering)
Two paths to embed PlantUML in a static blog: pre-render on the server, or have the reader’s browser render on the fly. Here’s the field guide.
Option A: Server-side render (hexo-renderer-plantuml)
Workflow: during hexo generate, the plugin replaces ```plantuml blocks with rendered SVG. Final HTML already contains the diagram; no client JS needed.
1 | # install |
Configure _config.yml:
1 | plantuml: |
Write the post:
1 | ```plantuml |
hexo generate calls plantuml.com for the SVG; the plugin writes it into the page:
1 | <svg xmlns="..." viewBox="..."> |
Pros
- Article HTML already contains the SVG; works with JS disabled
- SEO-friendly — crawlers can index the diagram
- Deploys to any static host (GH Pages, Gitee Pages, Cloudflare Pages)
Cons
- Build-time network requests to plantuml.com; flaky network = flaky builds
- Editing a diagram requires a full
hexo generate - Switching to a self-hosted renderer needs Java in your CI (
render: local)
Local render (render: local)
To keep your docs off plantuml.com’s radar, install Java:
1 | apt install default-jre |
1 | plantuml: |
hexo generate invokes Java to produce SVGs — entirely offline.
Option B: Client-side WASM render (TeaVM)
Workflow: the plugin emits <pre class="plantuml"> blocks. The browser runs the TeaVM-compiled plantuml.js to render each block into an SVG at view time.
Use a plain fenced code block:
1 | ```plantuml |
Drop the script into the theme layout:
1 | <script src="/vendor/plantuml.js"></script> |
Pros
- Zero backend dependency — CI just runs hexo
- Edit → refresh → see new diagram; fast iteration loop
- Articles continue to render even when the upstream renderer is down
Cons
- First page-load pulls ~7 MB of plantuml.js; costly on mobile
- TeaVM-compiled WASM has known bugs on class / state / use case / component / object / deployment diagrams
- No SEO value — crawlers don’t run JS
Option C: Self-hosted PlantUML server (the in-between)
When documentation quality matters more than load speed, and you don’t want to depend on plantuml.com:
1 | FROM plantuml/plantuml-server |
1 | plantuml: |
Run the PlantUML server on the internal network; hexo calls it during the build. External crawlers still won’t see diagrams, but every internal article is a real SVG.
Decision matrix
| Scenario | Pick |
|---|---|
| Public blog, infrequent updates | Option A (hexo-renderer-plantuml) |
| Frequent updates, internal docs, technical blog new project | Option B (client WASM) |
| Large team, internal-only, needs self-hosting | Option C (self-hosted server) |
| Don’t want to set up Java or any backend | Option B |
| Articles go to PDF / email / WeChat | Option A (pre-rendered SVG) |
How puml.online does it
This site is puml.online. The root (puml.online) is the blog entry point; the standalone /editor/ is the WASM editor.
- Blog posts: Option A —
hexo-renderer-plantumlcalls an internal API duringhexo generate. - Editor: Option B — TeaVM-compiled
plantuml.js+viz-global.jsvendor undersource/editor/vendor/.
The two are isolated: blog posts depend on no client scripts; the editor is an interactive real-time engine. Cleanest dual-stack.
Common pitfalls
- JS module ordering —
vendor/plantuml.jsis an ES module. Load it with<script type="module">or use the TeaVM-compiled IIFE, never mix. - TeaVM fails on class / usecase / state diagrams — the compiled WASM has a known bug at $jsException. Either switch to Option A for those diagrams, or rewrite them as sequence + activity equivalents.
- plantuml.com flakiness — public service often 502s from China. Self-host in production, or switch to
render: local. - Trailing whitespace / blank lines around
@enduml— the renderer is strict. Trim before publishing; if a sample renders in the editor but fails in the post, that’s where to look first.
- Title: Embedding PlantUML in Hexo (server vs client rendering)
- Author: puml.online
- Created at : 2026-07-29 14:25:00
- Updated at : 2026-08-14 21:34:29
- Link: https://puml.online/blog/plantuml-render-from-hexo-en/
- License: This work is licensed under CC BY-NC-SA 4.0.