Skip to content

Commit a647731

Browse files
add more detail around how to use bindings in React-Router Workers projects (#22850)
* add more detail around how to use bindings in React-Router Workers projects * Update src/content/docs/workers/frameworks/framework-guides/react-router.mdx Co-authored-by: Greg Brimble <[email protected]> * fix up missing import and formatting --------- Co-authored-by: Greg Brimble <[email protected]>
1 parent 26f80f9 commit a647731

File tree

1 file changed

+140
-49
lines changed

1 file changed

+140
-49
lines changed

src/content/docs/workers/frameworks/framework-guides/react-router.mdx

Lines changed: 140 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
Steps,
1212
Details,
1313
FileTree,
14+
WranglerConfig,
1415
} from "~/components";
1516

1617
**Start from CLI**: Scaffold a full-stack app with [React Router v7](https://reactrouter.com/) and the [Cloudflare Vite plugin](/workers/vite-plugin/) for lightning-fast development.
@@ -33,74 +34,164 @@ It combines with the [Cloudflare Vite plugin](/workers/vite-plugin/) to provide
3334
## Creating a full-stack React Router app
3435

3536
<Steps>
36-
1. **Create a new project with the create-cloudflare CLI (C3)**
3737

38-
<PackageManagers
38+
1. **Create a new project with the create-cloudflare CLI (C3)**
39+
40+
<PackageManagers
3941
type="create"
4042
pkg="cloudflare@latest"
4143
args="my-react-router-app --framework=react-router"
42-
/>
43-
<Details header="How is this project set up?">
44-
Below is a simplified file tree of the project.
45-
<FileTree>
46-
- my-react-router-app
47-
- app
48-
- routes
49-
- ...
50-
- entry.server.ts
51-
- root.tsx
52-
- routes.ts
53-
- workers
54-
- app.ts
55-
- react-router.config.ts
56-
- vite.config.ts
57-
- wrangler.jsonc
58-
</FileTree>
59-
60-
`react-router.config.ts` is your [React Router config file](https://reactrouter.com/explanation/special-files#react-routerconfigts).
61-
In this file:
62-
- `ssr` is set to `true`, meaning that your application will use server-side rendering.
63-
- `future.unstable_viteEnvironmentApi` is set to `true` to enable compatibility with the [Cloudflare Vite plugin](/workers/vite-plugin/).
64-
65-
:::note
66-
SPA mode and prerendering are not currently supported when using the [Cloudflare Vite plugin](/workers/vite-plugin/).
67-
If you wish to use React Router in an SPA then we recommend starting with the [React template](/workers/frameworks/framework-guides/react/) and using React Router [as a library](https://reactrouter.com/start/data/installation).
68-
:::
69-
70-
`vite.config.ts` is your [Vite config file](https://vite.dev/config/).
71-
The React Router and Cloudflare plugins are included in the `plugins` array.
72-
The [Cloudflare Vite plugin](/workers/vite-plugin/) runs your server code in the Workers runtime, ensuring your local development environment is as close to production as possible.
73-
74-
`wrangler.jsonc` is your [Worker config file](/workers/wrangler/configuration/).
75-
In this file:
76-
- `main` points to `./workers/app.ts`.
77-
This is the entry file for your Worker.
78-
The default export includes a [`fetch` handler](/workers/runtime-apis/fetch/), which delegates the request to React Router.
79-
- If you want to add [bindings](/workers/runtime-apis/bindings/) to resources on Cloudflare's developer platform, you configure them here.
80-
</Details>
44+
/>
45+
46+
<Details header="How is this project set up?">
47+
48+
Below is a simplified file tree of the project.
49+
50+
<FileTree>
51+
- my-react-router-app
52+
- app
53+
- routes
54+
- ...
55+
- entry.server.ts
56+
- root.tsx
57+
- routes.ts
58+
- workers
59+
- app.ts
60+
- react-router.config.ts
61+
- vite.config.ts
62+
- wrangler.jsonc
63+
</FileTree>
64+
65+
`react-router.config.ts` is your [React Router config file](https://reactrouter.com/explanation/special-files#react-routerconfigts).
66+
In this file:
67+
- `ssr` is set to `true`, meaning that your application will use server-side rendering.
68+
- `future.unstable_viteEnvironmentApi` is set to `true` to enable compatibility with the [Cloudflare Vite plugin](/workers/vite-plugin/).
69+
70+
:::note
71+
SPA mode and prerendering are not currently supported when using the [Cloudflare Vite plugin](/workers/vite-plugin/).
72+
If you wish to use React Router in an SPA then we recommend starting with the [React template](/workers/frameworks/framework-guides/react/) and using React Router [as a library](https://reactrouter.com/start/data/installation).
73+
:::
74+
75+
`vite.config.ts` is your [Vite config file](https://vite.dev/config/).
76+
The React Router and Cloudflare plugins are included in the `plugins` array.
77+
The [Cloudflare Vite plugin](/workers/vite-plugin/) runs your server code in the Workers runtime, ensuring your local development environment is as close to production as possible.
78+
79+
`wrangler.jsonc` is your [Worker config file](/workers/wrangler/configuration/).
80+
In this file:
81+
- `main` points to `./workers/app.ts`.
82+
This is the entry file for your Worker.
83+
The default export includes a [`fetch` handler](/workers/runtime-apis/fetch/), which delegates the request to React Router.
84+
- If you want to add [bindings](/workers/runtime-apis/bindings/) to resources on Cloudflare's developer platform, you configure them here.
85+
86+
</Details>
8187

8288
2. **Develop locally**
8389

8490
After creating your project, run the following command in your project directory to start a local development server.
91+
8592
<PackageManagers type="run" args="dev" />
86-
<Details header="What's happening in local development?">
87-
This project uses React Router in combination with the [Cloudflare Vite plugin](/workers/vite-plugin/).
88-
This means that your application runs in the Cloudflare Workers runtime, just like in production, and enables access to local emulations of bindings.
89-
</Details>
93+
94+
<Details header="What's happening in local development?">
95+
This project uses React Router in combination with the [Cloudflare Vite plugin](/workers/vite-plugin/).
96+
This means that your application runs in the Cloudflare Workers runtime, just like in production, and enables access to local emulations of bindings.
97+
</Details>
9098

9199
3. **Deploy your project**
92100

93-
Your project can be deployed to a `*.workers.dev` subdomain or a [Custom Domain](/workers/configuration/routing/custom-domains/) from your own machine or from any CI/CD system, including Cloudflare's own [Workers Builds](/workers/ci-cd/builds/).
101+
Your project can be deployed to a `*.workers.dev` subdomain or a [Custom Domain](/workers/configuration/routing/custom-domains/) from your own machine or from any CI/CD system, including Cloudflare's own [Workers Builds](/workers/ci-cd/builds/).
94102

95-
The following command will build and deploy your project. If you are using CI, ensure you update your ["deploy command"](/workers/ci-cd/builds/configuration/#build-settings) configuration appropriately.
103+
The following command will build and deploy your project. If you are using CI, ensure you update your ["deploy command"](/workers/ci-cd/builds/configuration/#build-settings) configuration appropriately.
96104

97-
<PackageManagers type="run" args={"deploy"} />
105+
<PackageManagers type="run" args={"deploy"} />
98106

99107
</Steps>
100108

101109
## Use bindings with React Router
102110

103111
With bindings, your application can be fully integrated with the Cloudflare Developer Platform, giving you access to compute, storage, AI and more.
104-
As you have direct access to your Worker entry file (`workers/app.ts`), you can also add additional exports such as [Durable Objects](/durable-objects/) and [Workflows](/workflows/).
112+
113+
Once you have configured the bindings in the Wrangler configuration file, they are then available within `context.cloudflare` in your loader or action functions:
114+
115+
```ts title="app/routes/home.tsx"
116+
export function loader({ context }: Route.LoaderArgs) {
117+
return { message: context.cloudflare.env.VALUE_FROM_CLOUDFLARE };
118+
}
119+
120+
export default function Home({ loaderData }: Route.ComponentProps) {
121+
return <Welcome message={loaderData.message} />;
122+
}
123+
```
124+
125+
As you have direct access to your Worker entry file (`workers/app.ts`), you can also add additional exports such as [Durable Objects](/durable-objects/) and [Workflows](/workflows/)
126+
127+
<Details header="Example: Using Workflows">
128+
129+
Here is an example of how to set up a simple Workflow in your Worker entry file.
130+
131+
```ts title="workers/app.ts"
132+
import { createRequestHandler } from "react-router";
133+
import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from 'cloudflare:workers';
134+
135+
declare global {
136+
interface CloudflareEnvironment extends Env {}
137+
}
138+
139+
type Env = {
140+
MY_WORKFLOW: Workflow;
141+
};
142+
143+
export class MyWorkflow extends WorkflowEntrypoint<Env> {
144+
override async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
145+
await step.do("first step", async () => {
146+
return { output: "First step result" };
147+
});
148+
149+
await step.sleep("sleep", "1 second");
150+
151+
await step.do("second step", async () => {
152+
return { output: "Second step result" };
153+
});
154+
155+
return "Workflow output";
156+
}
157+
}
158+
159+
const requestHandler = createRequestHandler(
160+
() => import("virtual:react-router/server-build"),
161+
import.meta.env.MODE
162+
);
163+
164+
export default {
165+
async fetch(request, env, ctx) {
166+
return requestHandler(request, {
167+
cloudflare: { env, ctx },
168+
});
169+
},
170+
} satisfies ExportedHandler<CloudflareEnvironment>;
171+
```
172+
173+
Configure it in your Wrangler configuration file:
174+
175+
<WranglerConfig>
176+
177+
```toml
178+
[[workflows]]
179+
name = "my-workflow"
180+
binding = "MY_WORKFLOW"
181+
class_name = "MyWorkflow"
182+
```
183+
184+
</WranglerConfig>
185+
186+
And then use it in your application:
187+
188+
```ts title="app/routes/home.tsx"
189+
export function action({ context }: Route.LoaderArgs) {
190+
const instance = await env.MY_WORKFLOW.create({ params: { "hello": "world" })
191+
return { id: instance.id, details: instance.status() };
192+
}
193+
```
194+
195+
</Details>
105196
106197
<Render file="frameworks-bindings" />

0 commit comments

Comments
 (0)