UNPKG

workflow

Version:

Workflow SDK - Build durable, resilient, and observable workflows

217 lines (149 loc) • 4.42 kB
--- title: React Router v8 description: Add durable workflows to a React Router v8 framework-mode app using Nitro v3. type: guide summary: Configure React Router v8, Nitro v3, and Workflow SDK in one Vite build. prerequisites: - /docs/getting-started/react-router related: - /docs/getting-started/nitro - /docs/foundations/workflows-and-steps --- This guide starts with an existing React Router v8 framework-mode app. <Steps> <Step> ## Install Nitro and Workflow SDK <CodeBlockTabs defaultValue="pnpm"> ```bash tab="npm" npm install nitro workflow ``` ```bash tab="pnpm" pnpm add nitro workflow ``` ```bash tab="bun" bun add nitro workflow ``` ```bash tab="yarn" yarn add nitro workflow ``` </CodeBlockTabs> This integration requires Nitro v3. </Step> <Step> ## Use a shared build directory Set an explicit build directory in your React Router config: ```typescript title="react-router.config.ts" lineNumbers import type { Config } from "@react-router/dev/config"; export default { ssr: true, buildDirectory: "build", // [!code highlight] } satisfies Config; ``` React Router will place browser assets in `build/client`. Nitro will place the runnable server in `build/server`. </Step> <Step> ## Create the React Router server handler Create `server/ssr.ts`: ```typescript title="server/ssr.ts" lineNumbers import { createRequestHandler } from "react-router"; export default { fetch: createRequestHandler( () => import("virtual:react-router/server-build"), import.meta.env.MODE, ), }; ``` This adapts React Router's generated server build to the Fetch API handler Nitro expects. </Step> <Step> ## Configure Vite Update `vite.config.ts`: ```typescript title="vite.config.ts" lineNumbers import { reactRouter } from "@react-router/dev/vite"; import { nitro } from "nitro/vite"; import { defineConfig } from "vite"; import { workflow } from "workflow/vite"; import reactRouterConfig from "./react-router.config"; export default defineConfig({ plugins: [ reactRouter(), nitro({ serverDir: "./server", output: { dir: reactRouterConfig.buildDirectory, serverDir: `${reactRouterConfig.buildDirectory}/server`, publicDir: `${reactRouterConfig.buildDirectory}/client`, }, }), workflow({ dirs: ["workflows"] }), ], environments: { ssr: { build: { rollupOptions: { input: "./server/ssr.ts", }, }, }, }, }); ``` Keep `dirs: ["workflows"]` so subsequent builds do not scan generated files under `build`. Place `reactRouter()` before `nitro()` in the plugin array. </Step> <Step> ## Create a workflow Create `workflows/greeting.ts`: ```typescript title="workflows/greeting.ts" lineNumbers export async function greetingWorkflow(name: string) { "use workflow"; return greet(name); } async function greet(name: string) { "use step"; return `Hello, ${name}!`; } ``` </Step> <Step> ## Start the workflow from a Nitro route Create `server/routes/api/greeting.post.ts`: ```typescript title="server/routes/api/greeting.post.ts" lineNumbers import { defineHandler } from "nitro"; import { start } from "workflow/api"; import { greetingWorkflow } from "../../../workflows/greeting"; export default defineHandler(async (event) => { const { name } = (await event.req.json()) as { name: string }; const run = await start(greetingWorkflow, [name]); return { runId: run.runId }; }); ``` React Router continues to handle your application routes. Nitro handles this server route at `POST /api/greeting`, as well as Workflow SDK's internal routes. </Step> <Step> ## Run the app Start the development server: ```bash pnpm vite dev ``` Then start a workflow: ```bash curl -X POST \ -H "content-type: application/json" \ -d '{"name":"Workflow"}' \ http://localhost:3000/api/greeting ``` Build and start the production server: ```bash pnpm vite build node ./build/server/index.mjs ``` You can inspect local runs with `pnpm workflow web`. </Step> </Steps> ## Troubleshooting ### React Router pages return 404 Check that the `ssr` environment input points to `./server/ssr.ts`. ### A second build tries to compile files under `build/server` Use `workflow({ dirs: ["workflows"] })`, remove the existing `build` directory once, and rebuild. ### `vite build` finishes output but does not exit Use `workflow@5.0.0` or later with Nitro v3.