【趣味】RustでSSGを自作してみる
これはIwaken Lab.アドベントカレンダーの17日目の記事です!
概要
こちらが今回制作したもののリポジトリと実際のページです!
なんちゃってではありますが、割とそれっぽくなってるんじゃないでしょうか。
特徴として、前々からちょっとやってみたかった階層化されたリンク集みたいなものを目指して作成してみました。
今回はこれのテック的な部分をコードをなぞりつつ書いていきます。
Node
このNode型をベースとしてデータをロード、各ページを描画するものとなっています。
ローダー
jsonとmarkdownのローダーが用意してあります。
Json
シンプルJsonローダー
Markdown
jsonだけで十分っちゃ十分なのですが、個人的に色々使いまわしたいかもなーと思いちょっと頑張りました。
(ただ普通に時間かかったので、あまりよくなかったかも)
ファイルロード→塊ごとに分割

こんな感じで、<ヘッダ>+<その下のテキスト全部>みたいな形で分割します。
構文解析のライブラリはあるっぽいのでこっちでやったほうが幸せかもしれない。
Node型への変換。さっきの塊のヘッダのレベルとヘッダ名で分岐して突っ込んでいきます。optionsをジェネリックにしたことを後悔しながら書いてました。
一応各種プロパティ用のパースが切り替えられるようになってます。
操作
オプショナルですが、デフォルトのNode型では貧弱なためいくつかのよく使うデータの拡張・操作をまとめています。
fill_dependents
Node型には一方的な依存方向のデータ(dependencies)しかないため、逆方向のデータ(dependents)を自動作成する関数。 内部はシンプルなマップ。
label_slug_map
空白などを含む単語対策。
どちらかというと型解決に苦労しました。
最終的にはhasとmaybeを用意して、独自のoptions型にmacroで保証させる。ということをやってます。
optionsをジェネリックにs...(略
正直このジェネリックはなんか間違っている気がします。おしえてえらいひと
描画
やっとssgっぽいことをします。今回はteraというテンプレートエンジンを使用しました。
初期化して基礎プロパティを入れて、
[名前: リンク先]の配列を作ってから、各ページを描画。
リンク先の解決は、もうちょっといい方法がある気はしています。
テンプレート側はこんな感じ。継承や埋め込みもできて良い感じ。
node_page側のimportもbase側に書かないとエラーが出て、そこだけ悩ましい。ちょっと複雑な運用しすぎてるんかなぁ~うーん。 こういうidを真面目に振るの、ssgっぽくてとても楽しい。(書いてから気づいたけどidじゃなくてclassのイメージもある。)
実行、CI/CD
実行部分はこんな感じ。mdをロードして、dependents埋めて、distをクリア、レンダー、distにpublicをコピー。
デプロイはこう。これは完全にmade in ai
generate static siteは0sだけど、buildに結構時間かかっちゃってる~もうちょっと早くならんかな

終わりに
ココまでお付き合いいただきありがとうございました。
テンプレートエンジンが強力で、案外ssg自体はシンプルに構築できるな~と思いました(拡張や最適化は絶対辛いけど)
Rustに関しては、docsも読まず、メモリとかほぼ意識せずに書いたため全く使いこなせている気はしませんが、ローダー部分以外では変なエラーで詰まる。みたいなことがなく片鱗は感じられた気がしています。
とりあえず前からあったRustを触りたい欲がほどほどに満たされて個人的には満足です(ポートフォリオをコレで作り直したいと考えてるので、もうちょっとやりますが)。次はmoonbitを触りたい。
Discussion