このサイトは Workflowy をバックエンドに使った自作の仕組みで動いている。記事を Workflowy で書いて特定のタグをつけておくと、GitHub Actions が自動でデータを取得してサイトに反映される、というものだ。
アウトライナーの項目がそのまま記事化する、という仕組みはめちゃくちゃ気に入っているんだけど、記事が増えるにしたがってページの表示が遅くなってきた。
この問題が仕組みを変えることで改善したので、その記録を残しておく。
なぜ遅くなってしまったか
もともとの仕組みはこういう流れだった。
- ページを開く
- JavaScript が data.json(Workflowyの項目から変換した全記事のメタデータを含むファイル) を取得する
- JSON のデータをもとに記事の内容を組み立ててDOMに書き込む
- 記事が表示される
このうち2,3番目のフェーズがボトルネックだった。data.json には全記事の本文HTMLが丸ごと入っているので、記事が増えるにつれてファイルが肥大化していく。そのためトップページの記事一覧を表示するだけでも、使いもしない全記事の本文を読み込む必要があったわけだ。
解決策:ビルド時にHTMLを作ってしまう
解決策はシンプルで、記事ごとの HTML ファイルをビルド時に生成しておくというもの。いわゆる静的サイト生成(SSG)と呼ばれるアプローチで、Next.js や Hugo がやっていることと本質的には同じ(らしい)。
ビルドは GitHub Actions が1日2回回しているので、Workflowy で記事を書いてタグをつけておけば、最大12時間以内に静的なHTMLファイルとして書き出されて自動でサイトに反映される。
これで記事ページにアクセスしたときは最初から完成したHTMLが返ってくるので、JavaScriptが動く前から内容が表示されるようになった。
トップページの記事一覧も別ファイルに
もうひとつ対応したのがトップページの記事一覧だ。
もとのコードはトップページを開くたびに data.json を読んで一覧を動的に組み立てていたが、ここも同じ問題がある。一覧表示に必要なのは記事のタイトルと日付だけなのに、全本文が入った巨大なファイルを毎回読み込んでいた。
対策として、ビルド時にタイトルと日付だけからなる articlelist.html というフラグメントファイルを生成するようにした。トップページはこれを読み込んで innerHTML に流し込むだけ。JavaScriptがやる仕事がほぼなくなった。
やってみて
表示速度は体感でもわかるくらい改善した。特に記事ページに関しては爆速!
副産物として OGP(SNSシェア時のタイトルや説明文)が記事ごとに正しく設定されるようになったのも地味にうれしい。これまでは JavaScript が動いてからページタイトルを書き換えていたので、SNS のクローラーには空のページとして認識されていた。
自作サイトのいいところは、こういう改善を自分のペースでちまちまできることだよね〜。