元々このサイトはNext.jsで生成される静的サイトで、以下のようになっていた。
- Next.jsによるStatic Site Generation
- Next.jsのライフサイクル
getStaticPaths[yyyy]_[mm][dd].jsなファイルの一覧を取得- 中身は
export default { title: string, content: HTML }なJSX(としてHTMLを持つJSオブジェクト) - ただし、ここでは中身は読まず、nodeのfs.readdirでファイル名のみ集める
- 中身は
- Next.jsのDynamic Routesで
posts/[yyyy]/[mm]/[dd]なパス(とページ)を生成
getStaticProps[yyyy]_[mm][dd].jsなファイルの一覧を取得(同上)- 各ファイルの情報をシリアライズ可能なJSオブジェクトとして用意する(つまりJSX等を渡せない)
- Next.jsのpage / Reactのライフサイクル
- JSXとしてHTMLを持つ各ファイルをdynamic importしてページを作る
- Next.jsのライフサイクル
いろいろと改善はしたけど、2022/04/23 JSX as dataと2021/01/02 Next.jsとPHPと私で書いたときとほぼ同じ。App Routerには移行せずPage Routerのまま。十分楽しんだし、そろそろNext.jsから離れるか、ということで書き換えて、以下のようになった。
- nodeで実行
- tscでJSXと.tsをESモジュールに変換
[yyyy]_[mm][dd].jsなファイルの一覧を取得- JSXとしてHTMLを持つ各ファイルをdynamic importする
- renderToStaticMarkupで静的なHTMLを出力する
- Reactでページを作る
- tscでJSXと.tsをESモジュールに変換
実行順じゃなくて依存ツリー(?)なので注意。Next.jsのライフサイクルから解放された結果、JSX(を含むJSオブジェクト)のdynamic importを早めに行えるようになり、Reactのライフサイクル内では非同期実行を含まなくなった。あれ?(tscのコンパイル時にはdynamic importは実行されてないのに)コンパイル後のESモジュールがJSXをimportできるのは何故なんだろう。何か勘違いがありそう。ちなみに、renderToStaticMarkupはレガシーなAPIらしく、prerenderToNodeStreamだとサスペンスの解決まで待てるから非同期処理も含められて、かつ、「クライアントで React をまったく実行したくない場合」としてhydrationしない場合への言及もあるから、たぶん移行できるはず。そのうちやる。
HTMLで書きたいが、そのままでは辛い。だからJSX。Reactじゃなくていいのかもしれないけど、そこで道を踏み外すのは辛そうだし十分に好きだからReact。そして静的サイトが欲しくて、かつ、面白そうだったからNext.js。という流れの最後を差し替えたのが今回。いろいろと整理した後だったから割とすんなり。動いていないはずのCSSがNext.js版では動いていることが分かり、謎が解けないから仕方なく正しいものに直したりはした。あとTypeScript関連でも似たような謎があった気がする。
Live Reload的なものが失われたから、次はそれをどうにかしたい。そういうライブラリを使えばいいんだけど、依存を減らしたいから自分で書きたくて、Server-Sent Eventsを使ってどうにかする。開発用のサーバを書く感じ。最終的にこの部分はSwiftで書いてもいいかもなあ。