最初に
以下の記事でHono + Vueの組み合わせを紹介しました。以下の記事では本題から逸れる為、詳しい設計については説明しなかったのでこの記事を執筆しました。
Honoを採用する場合フロントエンドは以下が主な選択肢となります。
- React
- HonoX
- 他フレームワークとの併用
しかしそれ以外に最近登場した方法としてInertia.jsを使う方法があります。
Inertia.jsによってReact/Vue/Svelteを従来より手軽にフロントエンドで使用することが可能です。
実装例
以下が実装例になります。
上記のリポジトリはHono作者のexampleを参考にしたものです。
Hono + Inertia.js + Vueの場合は以下のような順番で処理が走ります。
1. Vueページの自動検出
以下が app/pages/*.vue をスキャンし、app/pages.gen.tsを自動生成します。
import { inertiaPages } from "@hono/inertia/vite";
inertiaPages({ extensions: ["vue"] })
自動生成されたapp/pages.gen.tsは以下のようなコードになっています。
// AUTO-GENERATED by @hono/inertia/vite. Do not edit.
import type app from "./server";
export type PageName = "Error404" | "Home";
declare module "@hono/inertia" {
interface InertiaPages {
Error404: unknown;
Home: unknown;
}
interface AppRegistry {
app: typeof app;
}
}
export type { PageProps } from "@hono/inertia";
これによって型チェックやエディターの補完機能を利用することが可能になります。
2. フロントエンド側のバンドル
@vitejs/plugin-vueがapp/client.tsをエントリに、.vueをSFC(単一ファイルコンポーネント)にコンパイルするように設定しています。 (該当コード)
結果はdist/clientに出力されます。
3. Worker(SSR)のバンドル
@cloudflare/vite-pluginがwrangler.jsoncのmain: "./app/server.ts"を見て、Cloudflare Workers 環境向けにサーバーコードをビルドします。 (該当コード)
以下の部分で呼び出されているapp/root-view.tsxのrootViewが各リクエストでapp/ssr.tsのrenderPageを呼び、@vue/server-rendererのrenderToStringでVueコンポーネントをSSRレンダリングします。
const app = new Hono<{ Bindings: CloudflareBindings }>();
app.use(inertia({ rootView }));
これによってHonoのc.renderを使って行ったVueのレンダリングが実際のウェブサイトに適応されます。
vite-ssr-componentsの<ViteClient /> <Script> <Link>はdev時はHMR用タグ、build時は実際の生成済みアセットパスになります。
4. environments.ssr の特殊処理
vite-ssr-componentsが内部的にもう1つのssr environmentを生成してしまうため、vite.config.tsでダミーのentry (./app/server.ts) とemptyOutDir: falseを明示的に設定しています。
これがないと1~3までの処理によって作られたdist配下の生成物を空にしてしまいます。
5. Deploy (おまけ)
1~4の処理によってdist配下にworker本体と静的アセットが揃っているので後はwrangler deployをするだけです。
注意点: Deploy時にデータベース等に個別にマイグレーションが必要な場合はwrangler deployだけでは駄目なので気を付けてください
最後に
実装例でも示したようにHono + Inertia.jsの組み合わせでReact/Vue/Svelteをフロントエンドで手軽に使用可能です。
CloudFlare Workers + Honoでウェブサービスを作る際は是非Inertia.jsの採用も考えていただけると幸いです。
宣伝
TwitterとGitHubも良かったらフォローお願いします。