このブログをCMSなしで作った理由静的HTMLという選択
技術ブログにCMSもSSGフレームワークも使わず、Node標準ライブラリだけの自作ビルドで静的HTMLを吐く構成にした。道具の複雑さを問題の複雑さに合わせるという設計判断の記録。
問題設定:ブログに、どれだけの機構が要るか
このブログを立ち上げるとき、最初に決めたのは「何を使わないか」だった。技術ブログを作ると聞けば、WordPressのようなCMSを立てるか、あるいはSSGフレームワークを引いてくるのが今どきの定石だろう。どちらも実績があり、機能も豊富だ。だが少し立ち止まって考えた。ここで解きたい問題は、突き詰めれば「Markdownで書いた文章を、読める形のHTMLにして置く」ことでしかない。その一点に対して、データベースや管理画面やプラグイン機構は、明らかに過剰だ。
過剰な道具は、それ自体が新しい問題を連れてくる。バージョン追従、依存の脆弱性、管理画面への不正アクセス、そして数年後に「このスタック、まだメンテされているのか」という問いだ。書きたいのは文章であって、フレームワークの面倒を見ることではない。そこで、CMSもフレームワークも使わず、単一ディレクトリで自己完結する構成にした。
選んだ形:標準ライブラリだけの小さなビルド
構成は拍子抜けするほど単純だ。記事はposts/にMarkdownを1枚ずつ置く。ビルドスクリプトはNodeの標準ライブラリだけで書かれていて、外部依存はゼロ、npm installすら要らない。やることは、フロントマターを読み、本文をHTMLへ変換し、テンプレートに流し込んで書き出す、それだけである。
import { readdir, readFile, writeFile } from "node:fs/promises";
const files = await readdir("src/posts");
for (const name of files.filter(f => f.endsWith(".md"))) {
const raw = await readFile(`src/posts/${name}`, "utf8");
const { meta, body } = parseFrontMatter(raw); // 自前の小さな関数
const html = renderPage(meta, mdToHtml(body)); // これも自前
await writeFile(`dist/${meta.slug}.html`, html);
}
生成物はHTMLとCSSだけだ。サーバサイドで動くものは何もない。だからどんな環境にも置ける。静的ファイルを配れる場所ならどこでもいい。データベースが無いのでバックアップはdist/をコピーするだけで済み、管理画面が無いので不正ログインの入口も存在しない。攻撃面は限りなく小さい。記事を1本増やす手順も、.mdを1枚足してビルドを走らせるだけになった。
もちろん自作にはコストがある。MarkdownをHTMLに変換する処理は、既製ライブラリを一行呼べば済むところを、必要な記法に絞って自分で書いた。だがこの「必要な範囲に絞る」ができるのが自作の効用だ。使うのは見出し、段落、コードブロック、リンク、強調くらいで、仕様は自分の頭に全部入る。ブラックボックスをひとつも抱えないという状態は、規模が小さいうちだけ手に入る贅沢である。
トレードオフを正面から引き受ける
この選択は万能ではない。静的HTMLである以上、コメント欄も全文検索も認証も、素のままでは持てない。動的な機能が欲しくなったら、外部サービスを貼るか、結局どこかでサーバを持つことになる。ビルドという一手間も残る。書いてすぐ公開、とはいかない。
ただ、技術ブログという用途において、それらが本当に要るかは別の話だ。コメントは無くても困らないし、検索はブラウザのページ内検索とサイトマップで足りる。認証すべき秘密もない。つまり、諦めた機能はどれも、この用途では最初から不要だった。トレードオフを「引き受ける」というより、要らないものを渡して身軽になった、という感覚に近い。
依存の少なさは、寿命の長さに直結する。npmの巨大な依存ツリーは、更新を止めた瞬間から静かに腐り始める。標準ライブラリだけなら、ランタイムが動く限り同じように動く。10年後に開いても、たぶんこのビルドはそのまま通る。可搬性とは、突き詰めれば「未来の自分が理解と再現に困らないこと」だ。
AIとの協働作業での学び
道具の複雑さは、解きたい問題の複雑さに見合わせる。これは節約の話ではなく、設計の芯の話だ。強力な道具は、それが解く問題を自分が本当に抱えているときにだけ強力で、そうでなければ複雑さだけが手元に残る。まず問題を最小の形に見切り、それに釣り合う最小の機構を選ぶ。このブログ自体が、その小さな実例になった。