diff --git a/src/content/docs/workers/framework-guides/web-apps/tanstack.mdx b/src/content/docs/workers/framework-guides/web-apps/tanstack.mdx index c839df4e5a4a510..396131a61d4152d 100644 --- a/src/content/docs/workers/framework-guides/web-apps/tanstack.mdx +++ b/src/content/docs/workers/framework-guides/web-apps/tanstack.mdx @@ -5,18 +5,18 @@ sidebar: order: 7 head: [] tags: ["full-stack"] -description: Create a TanStack Router application and deploy it to Cloudflare Workers with Workers Assets. +description: Create a TanStack Start application and deploy it to Cloudflare Workers with Workers Assets. --- import { WranglerConfig, Steps, PackageManagers, Details } from "~/components"; ## What is TanStack Start? -TanStack Start is a full-stack React framework powered by TanStack Router. It provides a full-document SSR, streaming, server functions, bundling, and more using tools like Nitro and Vite. +TanStack Start is a full-stack React framework powered by TanStack Router. It provides a full-document SSR, streaming, server functions, bundling, and more using Vite and modern web standards. ## Create a new TanStack Start -TanStack provides a start-basic project. We'll use this starter project to create a new TanStack Start application. +TanStack Start Beta has significantly improved Cloudflare compatibility compared to the Alpha version, making deployment and development much more straightforward. @@ -27,10 +27,10 @@ TanStack provides a start-basic project. We'll use this starter project to creat cd start-basic npm install ``` - -
- This command will clone the TanStack Start basic project to your local machine, change directory to the project, and install the dependencies. TanStack [provides other examples](https://tanstack.com/start/latest/docs/framework/react/quick-start#examples) that you can use by replacing `start-basic` with the example you want to use. -
+ +
+ This command will clone the TanStack Start basic project to your local machine, change directory to the project, and install the dependencies. TanStack [provides other examples](https://tanstack.com/start/latest/docs/framework/react/quick-start#examples) that you can use by replacing `start-basic` with the example you want to use. +
2. **Develop locally** @@ -46,34 +46,33 @@ Whether you created a new TanStack Start project or are using an existing projec -1. **Install `unenv` & `nitroCloudflareBindings` package** - - [`unenv`](https://github.com/unjs/unenv) is a package that normalizes runtime environments across Node.js, browsers, and edge runtimes like Cloudflare Workers. It’s essential for TanStack Router because certain Node.js APIs are unavailable in the Workers environment. `unenv` offers compatible replacements for those APIs. - - [`nitro-cloudflare-dev`](https://github.com/nitrojs/nitro-cloudflare-dev) enables access to the Cloudflare runtime bindings like R2, D1, and other Cloudflare services in the development server. - - - -2. **Modify the `app.config.ts` file** - - To configure your application for Cloudflare Workers deployment, add the following lines to your `app.config.ts` file: - - ```ts - // Required imports - import { cloudflare } from 'unenv' - import nitroCloudflareBindings from "nitro-cloudflare-dev"; - - // Add this new server section to the defineConfig object - server: { - preset: "cloudflare-module", - unenv: cloudflare, - modules: [nitroCloudflareBindings], - }, +1. **Configure Vite for Cloudflare compatibility** + + Update your `vite.config.ts` file to use the `cloudflare-module` target for a compatible build: + + ```ts title="vite.config.ts" {14} + import { tanstackStart } from "@tanstack/react-start/plugin/vite"; + import { defineConfig } from "vite"; + import tsConfigPaths from "vite-tsconfig-paths"; + + export default defineConfig({ + server: { + port: 3000, + }, + plugins: [ + tsConfigPaths({ + projects: ["./tsconfig.json"], + }), + tanstackStart({ + target: "cloudflare-module", // Key configuration for Cloudflare compatibility + }), + ], + }); ``` - This will set the correct build format and runtime environment for Cloudflare. + This single configuration change is all that's needed to make your TanStack Start application compatible with Cloudflare Workers. -3. **Add a Wrangler file** +2. **Add a Wrangler file** Create a `wrangler.jsonc` or `wrangler.toml` file in the root of your project, `wrangler.jsonc` is the recommended approach. This file is used to configure the Cloudflare Workers deployment. @@ -82,23 +81,45 @@ Whether you created a new TanStack Start project or are using an existing projec ```json { "$schema": "node_modules/wrangler/config-schema.json", - "name": "start-basic", - "main": "./.output/server/index.mjs", - "compatibility_date": "2025-04-14", + "name": "my-start-app", + "main": ".output/server/index.mjs", + "compatibility_date": "$today", + "compatibility_flags": ["nodejs_compat"], + "assets": { + "directory": ".output/public" + }, "observability": { "enabled": true }, - "assets": { - "directory": "./.output/public/" - }, - "compatibility_flags": ["nodejs_compat"] + "kv_namespaces": [ + { + "binding": "CACHE", + "id": "" + } + ] } ``` - Note that the `directory` key is set to `.output/public/`, which is the folder that will be filled with the build output. Additionally, the `main` key is set to `.output/server/index.mjs`, indicating to Cloudflare Workers where to locate the entry point for your application. + Note that the `directory` key is set to `.output/public`, which is the folder that will be filled with the build output. Additionally, the `main` key is set to `.output/server/index.mjs`, indicating to Cloudflare Workers where to locate the entry point for your application. The `kv_namespaces` section shows an example of how to configure a KV namespace binding. + +3. **Add deployment scripts to package.json** + + Add the following scripts to your `package.json` file to streamline deployment and type generation: + + ```json title="package.json + { + "scripts": { + ... + "deploy": "npm run build && wrangler deploy", + "cf-typegen": "wrangler types --env-interface Env" + } + } + ``` + The `deploy` script combines building and deploying in one command, while `cf-typegen` generates TypeScript types for your Cloudflare bindings. + 4. **Build the application** You must build your application before deploying it to Cloudflare Workers. @@ -107,75 +128,104 @@ Whether you created a new TanStack Start project or are using an existing projec 5. **Deploy the application** - The command below will deploy your application to Cloudflare Workers and provide a deployment URL. Make sure to rebuild your application after making any changes to see those changes reflected in the deployment. + You can now use the deploy script to build and deploy your application in one command: + + + + Alternatively, you can still deploy directly with Wrangler: ```sh npx wrangler deploy ``` - When making changes in the future ensure you rebuild your application. The deploy will deploy what is in your `.output/public` folder and that only gets updated when you run the build command. - ## Using Cloudflare Bindings -1. **Create a helper function to get access to Cloudflare bindings** +1. **Generate TypeScript types for your bindings** - Create a helper function named `cloudflareBindings.ts` in the `src/utils` folder, and paste in the below code. You can create a `utils` folder in your project if you don't already have one. The example assumes you have a KV namespace with a binding name of `CACHE` already created in your account and added to the wrangler file. + Before using Cloudflare bindings in your code, generate the TypeScript types to ensure proper type safety: - ```ts - import type { KVNamespace } from "@cloudflare/workers-types"; + + + This command reads your `wrangler.jsonc` configuration and generates an `Env` interface with all your configured bindings. - interface CloudflareBindings { - CACHE: KVNamespace; +2. **Create a helper function to get access to Cloudflare bindings** + + Create a helper function named `bindings.ts` in the `src/utils` folder (create the folder if it doesn't exist), and paste in the below code. The example assumes you have a KV namespace with a binding name of `CACHE` already created in your account and added to the wrangler file. + + + ```ts title="src/utils/bindings.ts" + + let cachedEnv: Env | null = null; + + // This gets called once at startup when running locally + const initDevEnv = async () => { + const { getPlatformProxy } = await import("wrangler"); + const proxy = await getPlatformProxy(); + cachedEnv = proxy.env as unknown as Env; + }; + + if (import.meta.env.DEV) { + await initDevEnv(); } + /** * Will only work when being accessed on the server. Obviously, CF bindings are not available in the browser. * @returns */ - export async function getBindings() { + export function getBindings(): Env { if (import.meta.env.DEV) { - const { getPlatformProxy } = await import("wrangler"); - const { env } = await getPlatformProxy(); - return env as unknown as CloudflareBindings; + if (!cachedEnv) { + throw new Error( + "Dev bindings not initialized yet. Call initDevEnv() first." + ); + } + return cachedEnv; } - return process.env as unknown as CloudflareBindings; + return process.env as unknown as Env; } ```
- To ensure your bindings work locally with vinxi, the helper function uses - [getPlatformProxy](https://developers.cloudflare.com/workers/wrangler/api/#getplatformproxy) - method from wrangler. This logic is placed under a check if - import.meta.env.DEV is true. + The helper function uses [getPlatformProxy](/workers/wrangler/api/#getplatformproxy) method from wrangler to provide access to your Cloudflare bindings during local development. The bindings are cached at startup for better performance. In production, bindings are accessed via `process.env`. Make sure you've run `npm run cf-typegen` to generate the `Env` types that this code references.
-2. **Example using a Cloudflare Binding** +3. **Example using a Cloudflare Binding in Server Functions** - Now that you have a helper function to get access to your Cloudflare bindings, you can use them in your application. + Now that you have a helper function to get access to your Cloudflare bindings, you can use them in your server functions. Remember bindings are only available on the server. ```ts - const bindings = await getBindings(); - const cache = bindings.CACHE; - const queryCount = (await cache.get("queryCount")) || "0"; - await cache.put("queryCount", String(Number(queryCount) + 1)); + import { createServerFn } from "@tanstack/react-start"; + import { getBindings } from "~/utils/bindings"; + + const personServerFn = createServerFn({ method: "GET" }) + .validator((d: string) => d) + .handler(async ({ data: name }) => { + const env = getBindings(); + let growingAge = Number((await env.CACHE.get("age")) || 0); + growingAge++; + await env.CACHE.put("age", growingAge.toString()); + return { name, randomNumber: growingAge }; + }); ``` - A special thanks to GitHub user [backpine](https://github.com/backpine) for the code that supports Cloudflare Bindings in TanStack, which is demonstrated in their [TanStack Start on Workers example](https://github.com/backpine/tanstack-start-on-cloudflare-workers-v0). + A special thanks to GitHub user [backpine](https://github.com/backpine) for the code that supports Cloudflare Bindings in TanStack Start, which is demonstrated in their [TanStack Start Beta on Cloudflare example](https://github.com/backpine/tanstack-start-beta-on-cloudflare).
-#### Optional: Update utils file with deployment URL +## Environment Handling + +The TanStack Start Beta version provides seamless environment handling: -This step is required for the `/users` page to function properly in the `start-basic` example. Update the `/src/utils/users.tsx` file with the Cloudflare Workers deployment URL. +- **Development**: Bindings are accessed via [`getPlatformProxy()`](/workers/wrangler/api/#getplatformproxy) from Wrangler and cached at startup +- **Production**: Bindings are accessed via [`process.env`](/workers/runtime-apis/nodejs/process/#processenv) -```ts -export const DEPLOY_URL = "YOUR_DEPLOYMENT_URL"; -``` +This approach ensures your bindings are properly typed throughout your project and provides a smooth development experience. By following the steps above, you will have deployed your TanStack Start application to Cloudflare Workers.