Photo by SpaceX on Unsplash

Tepbyte.dev の技術構成

技術構成の話でお茶を濁します

このサイトの公開から一年が経っちゃったので、一度このサイトの技術構成についてまとめてみようと思います。

開発を始めた当初はとりあえず公開を目指して慣れている技術でぱぱっと開発しましたが、その中でもこだわった点があるのはもちろん、最近はより Tepbyte.dev に合った技術や気になった技術への移行が進んでいます。

ぜんたい的な構成

いわゆる Jamstack 的な構成になっています。
コンテンツを Markdown で記述、それをバックエンドでパースして、Next.js でレンダリングという流れです。

Markdown

Markdown は GitHub で管理しており、Webhook で更新時に処理するようにしています。
楽なので CMS や Notion を使うことも考えたのですが、なんとなく手元に置いておきたいですよね (ね)。

バックエンド

バックエンドのサービスは Firebase + Google Cloud に構築されています。
ランニングコストを無料に抑えるために特にネックになりがちなデータベースとして、使用経験があり無料枠もそこそこある Firestore を採用したので、その流れです。

フロントエンド

フロントエンドは普段から使い慣れている Next.js + Vercel です。
Tepbyte.dev は静的なサイトなので ISR (Incremental Static Regeneration) や App Router との相性がよく、Next.js の機能をしっかり活用できてるんじゃないかと思います。

ここからはもうちょっと詳しく見ていきます。👀👀👀

バックエンド

Nest.js を Cloud Run にデプロイしています。
Next.js じゃないです、一緒に使ってると一層ややこしいですね。

紹介しておいてなんですが、この構成には名前がややこしい以外にも少し課題を感じています

そこで Nest.js に変わるフレームワークとして、Hono への移行を進めています。
シンプルかつ高速で、エッジ向けに開発されているため、コールドスタートの課題を解決するためにも将来的にはそのまま Cloudflare への移行を考えています。
Cloudflare D1 で SQL が使えることもメリットです。

ドメインを始め最近 Cloudflare への依存度が高まりつつあります。まあ選んで依存してるんですけど。

また、Node でも最近高速になったらしく、移行中にも恩恵を得られそうで yay って感じです。
Hono の Node.js アダプタが 2.7 倍速くなりました - Zenn

実を言うと元々は Cloud Function for Firebase を使用していたので、2 度目の書き直しになっています。これが個人開発の醍醐味です。

処理の内容としては、GitHub から Webhook でコンテンツの更新を受け取り、Markdown はパースして Firestore に、画像は Cloud Storage にアップロードしています。
その後 On-Demand Revalidation のために Next.js に更新を通知し、API を通してデータを提供します。

Markdown の処理

Markdown パースには Unified を使用しています。

Tepbyte.dev では React での処理のしやすさを考え、Markdown を一般的な HTML の形式ではなく mdast という AST の形式にパースしています。
Unified はテキストコンテンツを構造化データとして処理することができ、ライブラリも充実しているため簡単に実装することができました。
すべての要素に対してコンポーネントを作成する必要がありクソ面倒ですが、満足度は高いです。

現状特に独自の記法などは実装しておらず、むしろ画像が貼れないなど基本的な機能が不足している状態ですが、一つ上げられるのは画像の処理です。
すべての画像で width, height などのメタデータを取得できるほか、ブラー画像が生成されるため初回読み込み時にいい感じに表示できます。ブラー画像は webp にするとなんかめっちゃ小さくなって面白かったです。
また、この投稿でも使用していますが、サムネイルの画像を Unsplash の URL で指定することができるようになっており、ライセンス表記のための情報が取得できるようになっています。
このようなデータの取得は HTML の形式では難しいので、お気に入りの便利機能です。

レンダリング

Next.js 以外にはスタイリング用のライブラリに依存しているくらいで、ほぼデータを取得して HTML に仕立てているだけです。

Tepbyte.dev では Next.js の最新機能である App Router をベータリリース当初から使用しており、Server Component の恩恵を得るには多くの UI ライブラリが使用できないため、UI コンポーネントはすべて自前で実装したものになっています。

スタイリングには Panda CSS を使用しています。
Panda CSS はかなり最近リリースされたライブラリで、Server Component に対応していることはもちろん普通にかなり使いやすく、Tailwind CSS から移行しています。
個人的には省略せず型の効くオブジェクト形式で書くほうがやりやすいです。

デザインにはちょっとだけコンセプトがあり、言うなればモダンレトロです。
メモ帳でホームページを作ろうとしていた身としては HTML 置いてるだけみたいなシンプルなサイトは結構好きで、どことなくそんな雰囲気が表現できたらいいなと思ってます。
今のところ全然そんな雰囲気は無いと思います。

まとめ

まだまだ不足している機能や改善が必要な箇所は多いです。将来的には Tepbyte.dev のシステムを CMS としてリリースしたいなーとも考えているので、ぼちぼち開発していきます。

(八割方汚いコードを見られたくなくて) 全然ソースコードを公開できていないので、こちらもぼちぼち。。。
フロントエンド周りのコードは公開しているので興味があったら見てみてください。
https://github.com/canoypa/tepbyte.dev