┌─────────────────────────────────────────┐ ┌────────────────────────────────────────┐ │ Main Worker (Spiceflow + Vite) │ │ Dedicated Worker (Spiceflow only) │ │ │ │ │ │ / ──> React pages │ │ /api/og ──> renderOgImage() │ │ /dashboard ──> React pages │ │ (WASM, heavy deps) │ │ │ │ │ │ /api/og ──> env.OG_WORKER.fetch(req) ──┼───────>│ No Vite plugin needed │ │ │ │ │ └─────────────────────────────────────────┘ └────────────────────────────────────────┘
services entry in the main Worker's wrangler.jsonc. Each environment needs its own binding pointing to the correct worker name for that environment.// main worker wrangler.jsonc { "services": [ { "binding": "OG_WORKER", "service": "my-og-worker" } ], "env": { "preview": { "services": [ { "binding": "OG_WORKER", "service": "my-og-worker-preview" } ] } } }
wrangler types after adding the binding so env.OG_WORKER is typed.// main worker src/main.tsx import { Spiceflow } from 'spiceflow' import { env } from 'cloudflare:workers' export const app = new Spiceflow() .page('/', async () => <div>Home</div>) .get('/api/og', ({ request }) => env.OG_WORKER.fetch(request)) export default { fetch(request: Request) { return app.handle(request) }, }
import() inside the handler to keep the heavy dependency out of the cold-start path; the module is only loaded when the route is actually called.// dedicated worker src/main.tsx import { Spiceflow } from 'spiceflow' import { z } from 'zod' const querySchema = z.object({ title: z.string(), description: z.string().optional(), }) export const app = new Spiceflow().route({ method: 'GET', path: '/api/og', query: querySchema, async handler({ query }) { // Dynamic import keeps WASM out of the cold-start path const { renderOgImage } = await import('./og.tsx') return renderOgImage(query) }, }) export default { fetch(request: Request) { return app.handle(request) }, }
wrangler.jsonc with preview and production environment configs. The main Worker's service binding resolves at request time, so the dedicated Worker must be live before the main Worker can call it.# Deploy dedicated worker first cd my-og-worker && wrangler deploy # Then deploy main worker cd my-main-worker && wrangler deploy