HonoX
とりあえず動かす。hono-cliを使い、basic-xのテンプレを選択する。
code:sh
npm create hono@latest
code:sh
npm install
npm run dev
これでHello, Worldページが動くはず。incrementだけできるCounterがついてる。
主要なアプリファイル群はapp/にある。client.tsとserver.tsがエントリーポイントっぽい。
一旦ビルドしてみる。クライアントモードとサーバーモード(デフォルト)で別々でビルドしてdist/に生成してる。
code:sh
npm run build
build
vite build --mode client && vite build
distの中身。
code:sh
% tree
.
├── _worker.js
└── static
├── client-qvhPWvF1.js
└── counter-BOkkX1zJ.js
_worker.tsはCloudflare PagesのFunctions用のコードだと思う。ということはstatic/のファイルがクライアント用のコードか。viteでクラ/サバそれぞれのビルドをして生成されてるっぽい。
本番デプロイに関しては_worker.jsが生成されていることからもわかるとおりCloudflare Pagesで動かすことが前提なようだ。yusukebeさんが今Cloudflareで働いているからこれはある意味、Next.js with Vercelに対するHonox with Cloudflareみたいなものか。だとするとCloudflareに依存してしまうので微妙か〜と思ったが、vite.config.tsをみてみると@hono/vite-cloudflare-pagesをpluginに指定してHonoをビルドさせているだけだった。つまり専用のpluginを作って(または使って)差し替えればHonoがサポートしてる他のプラットフォームでも使えそう。 File Based Routingについて。pathのルールはnext.jsと同じで/aboutはroutes/about/index.tsx。面白いのは同じtsxファイルのルートに複数のmethod(GET/POST/PATCH/DELETE)を定義できること。↓こんな感じでPOST/PATCH/DELETEをexportすれば良いだけ。これでPOST /aboutへのリクエストが処理できる。
code:tsx
export const POST = createRoute(async (c) => {
await new Promise((resolve) => setTimeout(resolve, 5000));
return c.redirect("/about/async");
});
export default createRoute((c) => {
return c.render(
<div class={className}>
<h1>About Page!</h1>
<br />
<form method="post" action="/about">
<button type="submit">Submit</button>
</form>
<br />
<a href="/">Home</a>
</div>,
{ title: "About" }
);
});
クライアント向けのコンポーネントはapp/islandに置くようになってる。この配下のコンポーネントがrouteで使われている場合、routeがSSRされた後コンポーネントの部分がクライアントに配信される。hono/jsxによく使いそうなuseXXXXがすでに結構実装されており凄い。インタラクションが必要な部分だけ雑にislandに切り出しまくっていくだけで大体済みそうで良い。
前の状態を保持しつつ次のページへ遷移していくみたいなこととか、グローバルで共有しておきたい状態がある、みたいな場合はどうやるといいのだろう。普通のSPAだとContextやJotaiみたいな機構を使うが。いわゆるMPAとかアイランドアーキテクチャの場合はそういうのどうやってるのか知らん...。
Contextあるじゃん!!
_renderer.tsxって何?何が嬉しい?
独自でrendererを定義できる。すなわちreactやpreactやsolidなど好きなフロントエンドライブラリを採用できる。
ということで合ってる?
アルファ版なので仕方ないが動作が微妙な点
開発サーバーを起動した状態で新規にtsxファイルを追加しても反映されないので再起動が必要
ホットリロードが結構遅い
tsconfig.jsonのcompilerOptions.libにdomを追加した方が良い(window.xxxとかの機能の型がエラーになるので)