NAKASHIMA CRAFT で開発を担当している中島Dです。
このたび、当ブログを Rust で書いた自前の SSG (Static Site Generator) で構築しました。 Hugo や Zola、Astro のような完成度の高い既存ツールが多数ある中で、なぜわざわざ自前で実装したのか。 その理由と、実際の構成についてまとめます。
#既存 SSG を採用しなかった理由
率直に申し上げると、Hugo や Zola を使えば 半日で立ち上げられたはずです。 それでもあえて自作を選んだ理由は、大きく 3 つあります。
#1. 本体サイトと同じ「ブランドの空気感」を維持したい
NAKASHIMA CRAFT のメインサイトは Leptos + Tailwind v4 + daisyUI v5 で構築しています。 ブログだけを別のテーマシステム(Hugo の Go テンプレートや Zola の Tera 等)で組んでしまうと、
- 配色や余白の単位がわずかにずれる
- アップデートのたびに 2 箇所をメンテナンスする必要がある
といった地味な摩擦が積み上がっていきます。Tailwind の生成 CSS を共有するためには、ビューを生成する側もそれを前提とした実装にした方が結果的に早い、と判断しました。
#2. SSG の中身は思いのほかシンプル
実のところ、SSG の本質は驚くほどシンプルです。
- Markdown ファイルを読み込む
- フロントマターをパースする
- Markdown → HTML に変換する
- テンプレートで囲む
- ファイルに書き出す
- RSS / sitemap / OGP も生成する
これだけです。 Rust にはこの各ステップに対応する成熟したクレートがあります:
pulldown-cmark— Markdown パーサgray_matter— フロントマター抽出maud— コンパイル時 HTML マクロsyntect— シンタックスハイライトresvg— SVG → PNG レンダリング (OGP 生成用)rss— RSS フィード生成
これらを組み合わせるだけで、500 行程度のコアコードでブログ用 SSG が完成します。
#3. 「やりたいこと」と「フレームワークの想定」はいずれズレる
長く運用する個人・企業のサイトでは、必ず「フレームワークの想定外のこと」をやりたくなる場面が訪れます。
- カテゴリ別の OGP 画像を自動生成したい
- 関連記事を独自ロジック(同一カテゴリ +3、共通タグ +1)で並べたい
- パンくずリストの構造化データを記事カテゴリと連動させたい
こうした要件は既存 SSG でもプラグインで対応できますが、プラグインを読み解くより自分のコードを読む方が早いという事実は、長期運用の生産性として決して無視できません。
#実際の構成
| 役割 | クレート / ツール |
|---|---|
| Markdown パーサ | pulldown-cmark 0.13 |
| フロントマター(TOML) | gray_matter 0.3 |
| HTML テンプレート | maud 0.27 |
| シンタックスハイライト | syntect 5.3 |
| OGP 画像生成 | resvg 0.45 + usvg + tiny-skia |
| RSS フィード | rss 2.0 |
| ローカル開発サーバ | axum 0.8 + tower-http |
| スタイル | Tailwind v4 + daisyUI v5 |
| デプロイ | Cloudflare Workers Assets |
Rust edition は 2024、rustc は 1.85 を要求しています。
#自作して得られた手応え
実際に自作してみて、ひとつ強い実感を得ました。
「自分の手の届くサイズの道具を、自分で組み上げる」ことの手応えは、 やはり大きなものでした。
大規模サイトにはまず向かない選択ですが、個人や小規模事業のブログ規模であれば、自作はむしろ運用負荷を下げる方向に働きます。 コードの全責任を自分が持っているため、何か起きてもまず自分のコードを読めば原因にたどり着けます。この安心感は、長く運用するほど効いてくるはずです。
詳しい実装については、ブログ本体のソースコードを今後 GitHub で公開する予定です。 ご興味のある方は、公開時にあらためてご覧いただけますと幸いです。