個人的なやつなので、すべての案件にハマるわけではないはず。
今回はたまたまAstroを選んでるけど、他のものを使ってSSGする場合にも、ある程度は当てはまる内容かと。
データの取得コマンドとSSGのコマンドを分ける
ビルドコマンドを叩いた時に、
- SSGのフローの一貫としてデータを`fetch()`し、それを使ってページ生成
というのではなく、
- データを取得し、ローカルにキャッシュするコマンド
- そのキャッシュを使って、SSGでページ生成するコマンド
という2段構えにするということ。
こうすることで、ローカルでの開発時にネットワーキングしなくて済む。
データ取得のコマンドを賢く作れば、毎回一括ダウンロードもしなくてよくなるし。
アーキテクチャにSSGを採用した場合、遅かれ早かれCMSからすべてのデータを引っこ抜くことになるので、そこだけを個別に最適化できるようにしたほうが絶対に幸せになれる。CMSに対してGraphQLで個別に・・とか本当にいらなくて、`all.json`だけあればあとはこっちでよしなに整形する。
そういう意味でも、各CMSベンダー各位がそれ用のCLIツールとか作ってくれていいのにって思ってる。だいたい手動でページング書かないといけなくてだるいので。
下書き記事のプレビューは、CSRする専用のページを作る
CMSへのアクセスに必要なキーは、URLのパラメータにするなりLocalStorageにしまうなりすればよい。
こうすれば、
SSG時に期待するであろう記事データを見て、静的にするか動的にするか書くだけ。
{Boolean(article) ? <StaticRenderer {article} /> : <DynamicRenderer client:only /> }
ディレクティブで`client:only`にしておけばよい。
Pagesにロジックを書かない
`pages/*.astro`でJSのコードをあれこれ書かないということ。
代わりに全部それ用の`.js`に逃がしてそこで書く。
--- export { getStaticPathsForArticlePages as getStaticPaths } from "../../data/index.js"; import { setupArticlePage } from "../../data/index.js"; const { article, relatedArticles, allCategories } = await setupArticlePage(Astro); --- <!-- 以降はそのまま -->
ただし、`Astro.glob()`だけは逃がせないらしい。
Make Astro global available outside of *.astro files · Discussion #190 · withastro/rfcs · GitHub
これは内部実装のViteプラグインの都合かと。
現状、AstroコンポーネントのDXは微妙であり、VSCode以外のエディタにとってはただのテキストファイルであることも踏まえると、まあ妥当かなーって。