-
Notifications
You must be signed in to change notification settings - Fork 309
Backport #2908: Fix Nitro cleanup for React Router and add setup guides #2923
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
github-actions
wants to merge
5
commits into
stable
Choose a base branch
from
backport/pr-2908-to-stable
base: stable
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
3ba0557
Fix Nitro cleanup for React Router and add setup guides (#2908)
github-actions[bot] d1f889d
fix Nitro React Router stable backport
NathanColosimo 3172986
scope Nitro cleanup to Vite builds
NathanColosimo 966bd59
merge stable into Nitro React Router backport
NathanColosimo 9da8dae
remove unnecessary esbuild service shutdown
NathanColosimo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| '@workflow/nitro': patch | ||
| --- | ||
|
|
||
| Clean up temporary Nitro Vite servers and Workflow build contexts after builds. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
| "title": "Getting Started", | ||
| "pages": [ | ||
| "next", | ||
| "react-router", | ||
| "astro", | ||
| "express", | ||
| "fastify", | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| --- | ||
| title: React Router | ||
| description: Run durable workflows in a React Router framework-mode app using Nitro. | ||
| type: overview | ||
| summary: Choose your React Router version and connect React Router, Nitro, and Workflow SDK. | ||
| related: | ||
| - /docs/getting-started/nitro | ||
| - /docs/getting-started/vite | ||
| - /docs/foundations/workflows-and-steps | ||
| --- | ||
|
|
||
| React Router framework mode builds the browser application and its server-rendering code, but it still needs a server to receive requests. [Nitro](https://v3.nitro.build) provides that server. Workflow SDK integrates with Nitro to add the durable workflow routes and build artifacts. | ||
|
|
||
| The three pieces share one Vite build: | ||
|
|
||
| 1. **React Router** builds your routes, loaders, actions, and browser assets. | ||
| 2. **Nitro** runs the React Router request handler and any routes in `server/routes`. | ||
| 3. **Workflow SDK** finds files with `"use workflow"` and `"use step"`, then adds its runtime routes to Nitro. | ||
|
|
||
| Choose the guide that matches your React Router major version: | ||
|
|
||
| <AutoCards /> | ||
|
|
||
| <Callout> | ||
| These guides require **Nitro v3**. Nitro v2 does not provide the Vite | ||
| environment integration used by this setup. | ||
| </Callout> | ||
|
|
||
| ## What the bridge does | ||
|
|
||
| The setup adds a small `server/ssr.ts` file. It turns React Router's generated server build into a standard Fetch API handler that Nitro can run. A small Vite plugin keeps React Router's client manifest where React Router expects it, while Nitro produces the output required by the selected deployment preset, such as `.output` for a local Node.js server or `.vercel/output` on Vercel. | ||
|
|
||
| This is configuration in your application, not a separate React Router adapter. Your React Router routes remain React Router routes, while Nitro owns the HTTP server and Workflow SDK uses Nitro's lifecycle and routing. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| { | ||
| "title": "React Router", | ||
| "pages": ["v7", "v8"], | ||
| "defaultOpen": true | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,239 @@ | ||
| --- | ||
| title: React Router v7 | ||
| description: Add durable workflows to a React Router v7 framework-mode app using Nitro v3. | ||
| type: guide | ||
| summary: Enable the Vite Environment API and configure React Router v7, Nitro v3, and Workflow SDK. | ||
| prerequisites: | ||
| - /docs/getting-started/react-router | ||
| related: | ||
| - /docs/getting-started/nitro | ||
| - /docs/foundations/workflows-and-steps | ||
| --- | ||
|
|
||
| This guide starts with an existing React Router v7 framework-mode app. It is verified with v7.18.1; if your config does not recognize `v8_viteEnvironmentApi`, update to the latest v7 release. | ||
|
|
||
| <Steps> | ||
|
|
||
| <Step> | ||
|
|
||
| ## Install Nitro and Workflow SDK | ||
|
|
||
| <Tabs items={["npm", "pnpm", "bun", "yarn"]} defaultValue="pnpm"> | ||
|
|
||
| <Tab value="npm"> | ||
|
|
||
| ```bash | ||
| npm install nitro workflow | ||
| ``` | ||
|
|
||
| </Tab> | ||
|
|
||
| <Tab value="pnpm"> | ||
|
|
||
| ```bash | ||
| pnpm add nitro workflow | ||
| ``` | ||
|
|
||
| </Tab> | ||
|
|
||
| <Tab value="bun"> | ||
|
|
||
| ```bash | ||
| bun add nitro workflow | ||
| ``` | ||
|
|
||
| </Tab> | ||
|
|
||
| <Tab value="yarn"> | ||
|
|
||
| ```bash | ||
| yarn add nitro workflow | ||
| ``` | ||
|
|
||
| </Tab> | ||
|
|
||
| </Tabs> | ||
|
|
||
| This integration requires Nitro v3. | ||
|
|
||
| </Step> | ||
|
|
||
| <Step> | ||
|
|
||
| ## Enable the Vite Environment API | ||
|
|
||
| React Router v7 keeps the Vite Environment API behind a future flag. Enable the required flag: | ||
|
|
||
| ```typescript title="react-router.config.ts" lineNumbers | ||
| import type { Config } from "@react-router/dev/config"; | ||
|
|
||
| export default { | ||
| ssr: true, | ||
| buildDirectory: "build", | ||
| future: { | ||
| v8_viteEnvironmentApi: true, // [!code highlight] | ||
| }, | ||
| } satisfies Config; | ||
| ``` | ||
|
|
||
| </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 { cp } from "node:fs/promises"; | ||
| import { resolve } from "node:path"; | ||
| import { defineConfig } from "vite"; | ||
| import { workflow } from "workflow/vite"; | ||
| import reactRouterConfig from "./react-router.config"; | ||
|
|
||
| export default defineConfig({ | ||
| plugins: [ | ||
| reactRouter(), | ||
| nitro({ serverDir: "./server" }), | ||
| { | ||
| name: "react-router-nitro-manifest", | ||
| applyToEnvironment: (environment) => environment.name === "client", | ||
| async writeBundle(options) { | ||
| await cp( | ||
| resolve(options.dir!, ".vite"), | ||
| resolve(reactRouterConfig.buildDirectory, "client/.vite"), | ||
| { recursive: true }, | ||
| ); | ||
| }, | ||
| }, | ||
| workflow({ dirs: ["workflows"] }), | ||
| ], | ||
| environments: { | ||
| ssr: { | ||
| build: { | ||
| rollupOptions: { | ||
| input: "./server/ssr.ts", | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| }); | ||
| ``` | ||
|
|
||
| The small `react-router-nitro-manifest` plugin copies React Router's Vite manifest back to `build/client` after Nitro writes the client build to its deployment output. Keep `dirs: ["workflows"]` so Workflow SDK only scans your source workflow directory. Do not set Nitro's `output.dir`; Nitro uses it to produce the output expected by each deployment preset. | ||
|
|
||
| </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 ./.output/server/index.mjs | ||
| ``` | ||
|
|
||
| You can inspect local runs with `pnpm workflow web`. | ||
|
|
||
| </Step> | ||
|
|
||
| </Steps> | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### Vite reports an invalid SSR input or `path.replace is not a function` | ||
|
|
||
| Set `future.v8_viteEnvironmentApi` to `true` in `react-router.config.ts`. | ||
|
|
||
| ### React Router pages return 404 | ||
|
|
||
| Check that the `ssr` environment input points to `./server/ssr.ts`. | ||
|
|
||
| ### `vite build` finishes output but does not exit | ||
|
|
||
| Use `workflow@4.6.1` or later with Nitro v3. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.