「SSG 専用コンポーネントライブラリ」という概念


ブログ等の静的サイトを生成したいときに、SPA 開発用の VDOM ライブラリやそれをベースにしたフレームワークを採用する実例が増えている。
しかし、全ページがビルド時に生成でき、かつブラウザ上では SPA としての副作用 (例えば非同期通信をしてその結果に応じてDOMを更新するとか) が必要ない場合、こういった技術選択はオーバーエンジニアリングな気がしてならない。
だから、SSG だけを目的としてビルドスクリプト中で利用されることを想定したコンポーネントライブラリが作れないか、という話

テンプレートエンジンを連想するかもしれないが、それだと以下のような要件は満たせないと思われる。
- 生成したいページを再利用可能なコンポーネントに細かく分解し、それぞれビルドスクリプト中で型安全に再利用できる
- コンポーネントごとに生成時の副作用を定義して、ビルドスクリプト実行中にそれぞれハンドリングする

ここでのコンポーネントは、VDOM ライブラリにおけるそれのようなライフサイクルの概念を持たない。
内容の決定に必要な副作用 (例えばヘッドレスCMSから記事の内容を取得するとか) が完了してビルドスクリプト中の値に一度落とし込まれたら、あとは HTML 文字列に書き出されるのみで、それ以外の状態遷移はしない。

このライブラリは開発/ビルド環境でのみ使用しブラウザには直接関与しないので、ビルドスクリプトのための適切な実行環境が構築できるなら JavaScript に限らずどのプログラミング言語で実装してもいいことになる。

実際の用途だと完全に静的にするという制約は厳しくないですか。
非常にシンプルなテキストサイトなら良くても、ブログとかだとJSでDOMをいじりたい場面は出てくるような

仰る通りですね…
この制約は「コンポーネントを安全に再利用するために、コンポーネント間でJSの実行時の依存関係を作るべきではないし、必要があったとしてもコンポーネントの依存関係と対応させるべき」という考えに基づいています。
制約にするのはさすがにやりすぎで、このような考えをドキュメントで強調する程度にするのが良さそうですね

SSG するのに nuxt とかは過剰というのは完全同意で、あれはそもそも SPA の副産物として出てきているので、SSG中心で再設計したミニマルなフレームワークとかはあっても良さそう

TSX (React 17+ New JSX Transform) で静的サイトのビルドスクリプトが組めたら面白そうだと思って、プロトタイプを作ってみた

このフレームワークを利用するプロジェクトのディレクトリ構造を考えてみた

よくよく考えたら「コンポーネント定義」「定義元のソースファイルのパス」「併せて指定されたランタイムスクリプトのパス」を管理しないとビルド時にどのランタイムスクリプトの読み込み用コードを書き出せばいいのかわからなくなる
よってコンポーネント定義・ランタイムスクリプトのパスはソースファイルと1対1対応にして、このフレームワークは Next.js のような CLI ツールとして作るしかない

この build.ts
のようにビルド対象のプロジェクト内にビルドスクリプトを置いてもらい、そこで使うためのヘルパー関数を提供するつもりだったが、先述のように CLI ツールとして作るならこの類のファイルは要らなくなる

この程度の問題は実装しなくても気づけそうだったのに、PoC 作ろうとしてみないと気づけないこともあるんだなぁと思った

Next.js のコードリーディングを始めた
SSG に関連する部分を集中的に読み進めている

HTML ファイルとして書き出す部分を実装して、JSX にも対応した

JSX に関する型定義を修正した