おそらくはそれさえも平凡な日々

HonoとCloudflare Pagesでプロフィールサイト兼短縮URLサービスを構築した

関連: NFCタグ入りの自己紹介アイコンバッジを自作する

song.mu という結構良い短いドメインを確保しているので、これをプロフィールサイト兼、個人用短縮URLサービスにしたいと長らく思っていたので重い腰を上げて作った。

最近オフラインイベントが増えている中で、こういうプロフィールサイトを活用しているケースを見るようになったのがきっかけ。Webエンジニアとしてはこういうの自作したいし、自分のドメインでホストしたいと思っていたのだ。

song.mu がリンクが並んだプロフィールページで、 song.mu/blog でブログに飛び、 song.mu/x でTwitterに飛ぶ、みたいな具合。

技術スタック

こういうの作る時は興味がある技術の砂場にしたいので、HonoSSGしてCloudflare Pagesでホストしている。ローカル開発でのTypeScript実行環境も mise で管理するようにして、ランタイムもBunを採用した。

当初はCloudflare Workersを使う想定だったが、別にリダイレクトするだけだったら、_redirects ファイルを生成するだけで良いということに気づいたのでPagesを使うことにした。短縮URL登録も別に動的に登録する仕組みを作らないで、設定を記述してサイトをデプロイすれば反映されるようにすればいいとは元々思っていた。以下のような build.ts を書いてサイトと_redirects ファイルを書き出している。

import { toSSG } from "hono/bun";
import app from "./src/index";
import { urls } from "./src/urls";

const comment = "# The following lines are generated by build.ts.\n";

const redirects = Object.entries(urls)
  .map(([key, site]) => `${key} ${site.url} 301`)
  .join("\n");

await Bun.write("static/_redirects", comment + redirects + "\n");

toSSG(app);

別にサイトのソースコードも公開しても良いと思っていたのだが、一部秘密にしておきたいURLも含まれてしまったので非公開にせざるを得なくなってしまった。

Hono

Honoは良かった。テンプレートがJSXで普通に書けるし、css HelperでCSSも普通に書けて、既存のフロント開発と同じ雰囲気で書ける。vim-jsx-prettyとかvim-styled-componentsでちゃんとシンタックスハイライトが利くのが嬉しい。

あと、Vite Plugins for Honoでvite使って開発できるのが良くて、高速なホットリロード体験が快適だった。

この辺、元々は標準APIのみ使うところからスタートしていたり、既存のエコシステムにうまく相乗りするように作られているところがセンスの良さを感じた。

Bun

Bunも良かった。速くて快適。コマンド体系的にも bunbunx コマンドのみでランタイムやパッケージマネージャーが備える一通りの操作をおこなえるのは明確。既存のコマンドに対するDrop in Replacementとして動くのがわかりやすい。

Cloudflare Pages

以前、このサイトを引っ越した時に利用を検討したのだけど,断念することになって残念だったので、今回使えて良かった。Cloudflareの管理画面からGitHubの連携設定が簡単で、すぐデプロイできるのはお手軽で良い。ただ、GitHubへの広い読み取り権限を渡してしまうので、GitHub Actionsでdeployする方法に変更するほうが安全で、柔軟にもなるので、そのうち切り替えたい。

ちなみに、Cloudflareの環境上でBunを使うためには、環境変数 BUN_VERSION を指定すればbunコマンドを利用できるようになる。

ref. https://developers.cloudflare.com/pages/configuration/language-support-and-tools/

ちなみに、ドキュメントはされていないが、asdfの .tool-versions を見てくれるという話もあるようで、ドキュメントされてほしいし、この記事に書いてあるようにmise.tomlもサポートされてほしい。

created at
last modified at

2024-08-09T22:18:13+0900

comments powered by Disqus