Open3
vite environment api で vite + workerd をワンストップで動かす
今までの問題
vite dev server でビルドしたSSR含むプログラムを workerd 環境で動かすには、一度(フル)ビルドしてから wrangler (workerd) で起動し直す必要があった。
vite6 の environment api を使うと、実行環境とビルドサーバー(vite dev)を分離できるので、 vite dev server の のインクリメンタルビルドに載せたまま workerd で動かすことができる。
npx create-vite でスキャフォルドしたプロジェクトを想定
やりたいこと
worker/index.ts # workerd のエントリポイント
client/main.tsx # react spa app
vite.config.ts
ここから vite dev 一発で起動する状態を作りたい。
やっていく。
$ npm install -D @cloudflare/vite-plugin
vite.config.ts で指定
import { defineConfig } from "vite";
import { cloudflare } from "@cloudflare/vite-plugin";
export default defineConfig({
plugins: [cloudflare({ persistState: false })],
});
wrangler.toml で worker/index.ts を指定しつつ、アセットハンドラを設定
name = "<your-app-name>"
main = "./worker/index.ts"
compatibility_date = "2024-12-30"
assets = { not_found_handling = "single-page-application", binding = "ASSETS"}
これで vite dev で両方立ち上がる。
デプロイするときは、 vite build && wrangler deploy で おk
$ pnpm vite build --app
vite v6.0.11 building for production...
✓ 27 modules transformed.
dist/client/index.html 0.37 kB │ gzip: 0.27 kB
dist/client/assets/index-9COutgvQ.js 143.40 kB │ gzip: 46.16 kB
✓ built in 401ms
vite v6.0.11 building SSR bundle for production...
✓ 1 modules transformed.
dist/react_spa/wrangler.json 1.03 kB
dist/react_spa/index.js 0.35 kB
✓ built in 9ms
worker の実装サンプル
worker/index.ts
interface Env {
ASSETS: Fetcher;
}
export default {
fetch(request, env) {
const url = new URL(request.url);
console.log(url.pathname);
if (url.pathname.startsWith("/api/")) {
const endpoint = url.pathname.replace("/api/", "");
return Response.json({
endpoint,
});
}
return env.ASSETS.fetch(request);
},
} satisfies ExportedHandler<Env>;
今回の設定では静的アセットが優先されるので、 env.ASSETS 側のハンドラは多分来ない。
これをフロントエンドから呼ぶサンプル
client/App.tsx
import { useEffect, useState } from "react";
function App() {
const [data, setData] = useState<any>(null);
useEffect(() => {
(async () => {
const response = await fetch("/api/hello");
const data = await response.json();
setData(data);
})();
}, []);
return (
<>
<h1>Vite + React</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</>
);
}
export default App;
同一のサーバープロセスとして振る舞っている。
今回は単純なSPA+APIエンドポイントを一つにしただけだが、これによって workerd 経由で vite SSR してたフレームワークの開発体験が大幅に向上する。
具体的には remix cloudflare adapter や qwik 等。
多少は各フレームワーク側の対応も必要だが、これで workerd でしか使えないAPIをフルビルド無しで開発できる基盤が整ったと言える。