記事の正本は、データベースに置かない

CMSといえば、記事はデータベースの中にある。ここに、私はずっと疑問を感じていました。

「記事は、DBじゃなきゃダメなのか?」

SE・プログラマーの目線で見ると、DBの中の記事は扱いづらいのです。記事全体をざっと見渡すことができない。まとめて直したいときも、一件ずつ画面を開いて編集するしかない。一括インポート・エクスポートの機能はあるにはありますが、気軽に使えるものではありません。

一記事ずつ、画面で見ながら書く人は、気にしたこともないと思います。でもプログラマーとしては、全記事をまとめて検索したり、置換したりできるほうがずっと扱いやすい。

とはいえ、そういう作りになっているのだから仕方ない。長いあいだ、そう思って付き合ってきました。

バックアップに、記事が入っていなかった

一度、こんな失敗をしています。バックアップのつもりでサイトのフォルダをまるごとコピーして、これで安心だと思っていたら、肝心の記事が入っていなかった。記事はフォルダの中ではなく、DBの中にあったからです。

サイトで一番大事な資産は記事です。それが、その仕組みの中でしか読めない、気軽に持ち出せない形になっている。この引っかかりが、ずっと残っていました。

一番の目的は、表示を爆速にすること

自分でCMSを作るとき、一番の目的ははっきりしていました。閲覧側を静的HTMLにして、とにかく速くすることです。

アクセスのたびにサーバーでページを組み立てる方式は、どうしても遅くなりがちで、セキュリティの心配もつきまといます。世の中の流れも、あらかじめ全ページを生成しておくSSG(静的サイト生成)へ変わってきています。それを、自分の手でもやってみたかった。

最初はNext.js系で組むつもりでした。前作のAK²Engineもその系譜です。ただ、セットアップまわりの扱いがどうしても大変で、結局、どこのサーバーにも簡単に設置できるPHPで設計し直しました。

ポイントは、PHPを使うのが設定と記事投稿のまわりだけ、というところです。訪問者が見るのは生成済みの静的HTMLなので、表示は速く、セキュリティ面でも安心です。もし動的な処理が必要になったら、その部分だけPHPで実装すればいい。この小回りの良さが気に入っています。

正本はMarkdown、DBは生成のときだけ

記事の正本は、フロントマター付きのMarkdownファイルにしました。タイトルも日付も分類も、本文と同じファイルに、人が読める形で入っています。

Markdownといっても、一般的なMarkdown書式だけではありません。中に普通にHTMLを書けますし、独自の書式も混ぜられます。テキストとしてそのまま読めて、凝りたいところでは自由にHTMLを書ける。この両取りが実現できました。発想自体はEleventyの受け売りですが、それを自分のシステムとして組み込んでみたかったのです。

データベース(SQLite)は、一覧・カテゴリ・タグ・全文検索のための索引として使います。動くのは生成のときだけで、訪問者のアクセスでDBが叩かれることはありません。

DBといえばMySQLのほうが堅牢ですが、管理画面を操作するのは原則1人です。複数アクセスがそもそも存在しないので、むしろSQLiteのほうが都合がいいのです。単一アクセスならSQLiteのほうが速く、DBサーバーを別に持つ必要もないので管理も楽です。設定でMySQLに切り替えられるようにはしてありますが、正直、SQLiteで十分でした。

この索引は、いつでもMarkdownから作り直せます。DBが壊れても、記事は一文字も失われません。

テキストに戻したら、不便が消えた

記事がただのテキストファイルになったことで、ずっと感じていた不便がいくつも解消しました。

  • エディタで全記事を見渡せて、一括検索・一括置換ができる
  • 変更の差分がgitで見える
  • 別のシステムに移ることになっても、Markdownはそのまま持っていける
  • バックアップはフォルダをコピーするだけ。今度は記事もちゃんと入っています

おわりに

記事をデータベースに預けなかったのは、DBが嫌いだからではありません。索引としてのDBは頼りになります。

ただ、一番大事なものを、一番扱いにくいものに預けたくなかった。それだけです。

正本は、人が読める形で、仕組みの外に置いておく。CMSが変わっても、サーバーが変わっても、最後に残るのは記事です。だからそこだけは、何にも依存させないことにしました。