なぜまた個人サイトを作ったのか
書く場所がなかったわけではなく、記事とゲームとツールを同じ場所に置けなかったから。
個人サイトの価値は「存在すること」ではなく「気軽に何かを足せること」だと思っています。これまで三回作り、三回とも同じ場所で頓挫しました。小さなゲームかツールを足そうとして、構造に拒まれるのです。
問題のかたち
要件を並べると、実は二種類あります。
- コンテンツ — 記事、プロフィール。速くて、インデックスされて、読み終わったら終わり。
- アプリ — ゲーム、ブラウザツール。操作があって、バンドルが制御されていて、障害が他に伝染しないこと。
ドキュメント向けフレームワークは「サイトはページの集まり」という前提で、アプリページもその一種として扱います。しかし canvas とキーボード入力と独自の状態を持つものは、Markdown の記事とはほとんど共通点がありません。
Astro を選んだ理由
最初の候補は VitePress でした。Vue に慣れていますし、単純です。それでも変えた理由が三つあります。
- ブログが標準で入っていない。タグ・アーカイブ・RSS はすべて
createContentLoaderの上に自作する必要があります。 - Markdown がそのままルーティングなので、純粋なアプリページは
xxx.mdで<ClientOnly>を包む形になります。 - 決定的だったのはビューポート単位の遅延読み込みがないこと。
defineAsyncComponentは描画時に読み込むのであって、画面に入ったときではありません。
Astro の islands はまさにこの三点目を解決します。読み込みだけでなくハイドレーションを遅らせることができます。そして @astrojs/vue があるので .vue の単一ファイルコンポーネントを書き続けられます。これまで覚えたことが無駄になりません。
このサイトの構成
3種類のページに、3つの方針を置いています。
| 種類 | 例 | JS の方針 |
|---|---|---|
| コンテンツ | ホーム、記事 | ほぼ素の静的 HTML、JS はほぼゼロ |
| インデックス | ブログ一覧、ゲーム一覧 | 静的な一覧。操作がある部分だけ別の island |
| アプリ | スネーク、JSON ツール | 静的な空殻 + 必要時のみ読み込む Vue アプリ |
記事を書くときにゲーム側を気にする必要はなく、その逆も同じです。欲しかったのはそれだけです。

コメント
…