追記
デプロイしてから分かったけど、production buildのみ図の描画がうまくいったりいかなかったりする。リロードしてみるとたまに表示できる。よくわからないので、SSRでの実装にするかも。
markdownみたいなかんたんな記法でフローチャートなどの図を描けるmermaid.jsをこのブログでサポートした。
たとえばこんな感じ。
graph TD
client
lb[alb]
app1[rails]
app2[rails]
db[mysql]
client --> lb --> app1 & app2 --> db
この図はこんなcode blockで書いている(エスケープだけしてある)。
\```mermaid
graph TD
client
lb[alb]
app1[rails]
app2[rails]
db[mysql]
client --> lb --> app1 & app2 --> db
\```
mermaid.jsをgatsbyで動かす
mermaid.jsはブラウザ上じゃないと動かすことができないため、gatsbyで動かすには
- クライアントサイドで動かす
- headless browserを利用してSSRする
の2通りしかない。
今回はより簡単にクライアントサイドで動かすようにした。既存のgatsby-remark-mermaidプラグインは後者を採用していてpuppeteerをつかっていた。ただ、試してみたところ自分の環境では動かなかったため、自作することにした。
Gatsbyで生成しているページはReactのコンポーネントでできているので、componentDidMount
やcomponentDidUpdate
のようなタイミングでmermaidを動かしている。
import mermaid from "mermaid";
class PostTemplate extends Component {
componentDidMount() {
const element = document.getElementById("mermaid");
mermaid.initialize({ startOnLoad: true });
mermaid.mermaidAPI.render("container", "graph TD\n a --> b", svg => {
element.innerHTML = svg;
})
}
}
あとは、remarkプラグインを書いて、mermaid
がついたcode blockを<div class="mermaid"></div>
で囲うように変換するようにした。
const visit = require("unist-util-visit");
module.exports = ({ markdownAST }, pluginOptions) => {
visit(markdownAST, "code", node => {
if (node.lang !== "mermaid") return;
node.type = "html";
node.value = `<div class="mermaid">\n${node.value}\n</div>`;
});
return markdownAST;
};