TanStack Start ↗ は、サーバーサイドレンダリング、ストリーミング、サーバー関数、バンドルを備えた、Web アプリケーション向けのフルスタックフレームワークです。
Cloudflare Workers 向けに事前設定された TanStack Start アプリケーションを作成します。
npm create cloudflare@latest -- my-tanstack-start-app --framework=tanstack-startyarn create cloudflare my-tanstack-start-app --framework=tanstack-startpnpm create cloudflare@latest my-tanstack-start-app --framework=tanstack-start開発中にプロジェクトをプレビューするローカル開発サーバーを起動します。
npm run devyarn run devpnpm run dev既存の TanStack Start アプリケーションがある場合は、Cloudflare Workers で動くように設定します。
-
@cloudflare/vite-pluginとwranglerをインストールします。npm i @cloudflare/vite-plugin wrangler -- -Dyarn add @cloudflare/vite-plugin wrangler -Dpnpm add @cloudflare/vite-plugin wrangler -Dbun add @cloudflare/vite-plugin wrangler -D -
Vite 設定に Cloudflare プラグインを追加します。
vite.config.jsjs import { defineConfig } from "vite"; import { tanstackStart } from "@tanstack/react-start/plugin/vite"; import { cloudflare } from "@cloudflare/vite-plugin"; import react from "@vitejs/plugin-react"; export default defineConfig({ plugins: [ cloudflare({ viteEnvironment: { name: "ssr" } }), tanstackStart(), react(), ], });vite.config.tsts import { defineConfig } from "vite"; import { tanstackStart } from "@tanstack/react-start/plugin/vite"; import { cloudflare } from "@cloudflare/vite-plugin"; import react from "@vitejs/plugin-react"; export default defineConfig({ plugins: [ cloudflare({ viteEnvironment: { name: "ssr" } }), tanstackStart(), react(), ], }); -
wrangler.jsonc設定ファイルを追加します。{ "$schema": "node_modules/wrangler/config-schema.json", "name": "<YOUR_PROJECT_NAME>", // Set this to today's date "compatibility_date": "2026-09-20", "compatibility_flags": ["nodejs_compat"], "main": "@tanstack/react-start/server-entry", "observability": { "enabled": true, }, }"$schema" = "node_modules/wrangler/config-schema.json" name = "<YOUR_PROJECT_NAME>" # Set this to today's date compatibility_date = "2026-09-20" compatibility_flags = [ "nodejs_compat" ] main = "@tanstack/react-start/server-entry" [observability] enabled = true -
package.jsonのscriptsセクションを更新します。package.jsonjson { "scripts": { "dev": "vite dev", "build": "vite build", "preview": "vite preview", "deploy": "npm run build && wrangler deploy", "cf-typegen": "wrangler types" } }
自分のマシン、または Workers Builds を含む任意の CI/CD システムから、*.workers.dev サブドメインまたは カスタムドメイン にデプロイします。
npm run deployyarn run deploypnpm run deployTanStack Start のデフォルトエントリポイントは @tanstack/react-start/server-entry です。カスタムのサーバーエントリポイントを作成すると、Queues や Cron Triggers などの追加の Workers ハンドラーを足せます。Durable Objects や Workflows などの追加のエクスポートも、ここで足せます。
-
カスタムのサーバーエントリポイントファイルを作成します。
src/server.jsjs import handler from "@tanstack/react-start/server-entry"; // Export Durable Objects as named exports export { MyDurableObject } from "./my-durable-object"; export default { fetch: handler.fetch, // Handle Queue messages async queue(batch, env, ctx) { for (const message of batch.messages) { console.log("Processing message:", message.body); message.ack(); } }, // Handle Cron Triggers async scheduled(event, env, ctx) { console.log("Cron triggered:", event.cron); }, };src/server.tsts import handler from "@tanstack/react-start/server-entry"; // Export Durable Objects as named exports export { MyDurableObject } from "./my-durable-object"; export default { fetch: handler.fetch, // Handle Queue messages async queue(batch, env, ctx) { for (const message of batch.messages) { console.log("Processing message:", message.body); message.ack(); } }, // Handle Cron Triggers async scheduled(event, env, ctx) { console.log("Cron triggered:", event.cron); }, }; -
Wrangler 設定を、カスタムエントリポイントを指すように更新します。
{ "main": "src/server.ts", }main = "src/server.ts"
/cdn-cgi/local/scheduled エンドポイントを使い、スケジュールハンドラーをローカルでテストします。
curl "http://localhost:3000/cdn-cgi/local/scheduled?cron=*+*+*+*+*"例: Workflows を使う
耐久性のある複数ステップのタスクを実行するには、カスタムエントリポイントから Workflow クラスをエクスポートします。
import {
WorkflowEntrypoint,
WorkflowStep,
WorkflowEvent,
} from "cloudflare:workers";
export class MyWorkflow extends WorkflowEntrypoint {
async run(event, step) {
const result = await step.do("process data", async () => {
return `Processed: ${event.payload.input}`;
});
await step.sleep("wait", "10 seconds");
await step.do("finalize", async () => {
console.log("Workflow complete:", result);
});
}
}import {
WorkflowEntrypoint,
WorkflowStep,
WorkflowEvent,
} from "cloudflare:workers";
export class MyWorkflow extends WorkflowEntrypoint<Env> {
async run(event: WorkflowEvent<{ input: string }>, step: WorkflowStep) {
const result = await step.do("process data", async () => {
return `Processed: ${event.payload.input}`;
});
await step.sleep("wait", "10 seconds");
await step.do("finalize", async () => {
console.log("Workflow complete:", result);
});
}
}Wrangler 設定に Workflow の設定を追加します。
{
"workflows": [
{
"name": "my-workflow",
"binding": "MY_WORKFLOW",
"class_name": "MyWorkflow",
},
],
}[[workflows]]
name = "my-workflow"
binding = "MY_WORKFLOW"
class_name = "MyWorkflow"例: サービスバインディングを使う
TanStack Start アプリケーションから別の Worker の RPC メソッドを呼ぶには、サービスバインディングを追加します。
{
"services": [
{
"binding": "AUTH_SERVICE",
"service": "auth-worker",
},
],
}[[services]]
binding = "AUTH_SERVICE"
service = "auth-worker"サーバー関数から、バインドした Worker のメソッドを呼び出します。
import { createServerFn } from "@tanstack/react-start";
import { env } from "cloudflare:workers";
const verifyUser = createServerFn()
.inputValidator((token) => token)
.handler(async ({ data: token }) => {
const result = await env.AUTH_SERVICE.verify(token);
return result;
});import { createServerFn } from "@tanstack/react-start";
import { env } from "cloudflare:workers";
const verifyUser = createServerFn()
.inputValidator((token: string) => token)
.handler(async ({ data: token }) => {
const result = await env.AUTH_SERVICE.verify(token);
return result;
});TanStack Start アプリケーションは、バインディング を使うと、ローカル開発でも本番でも Cloudflare Developer Platform と完全に統合できます。
サーバーサイドのコードでは、env オブジェクトをインポート してバインディングにアクセスします。
import { createFileRoute } from "@tanstack/react-router";
import { createServerFn } from "@tanstack/react-start";
import { env } from "cloudflare:workers";
export const Route = createFileRoute("/")({
loader: () => getData(),
component: RouteComponent,
});
const getData = createServerFn().handler(() => {
// Access bindings via env
// For example: env.MY_KV, env.MY_BUCKET, env.AI, etc.
});
function RouteComponent() {
// ...
}import { createFileRoute } from "@tanstack/react-router";
import { createServerFn } from "@tanstack/react-start";
import { env } from "cloudflare:workers";
export const Route = createFileRoute("/")({
loader: () => getData(),
component: RouteComponent,
});
const getData = createServerFn().handler(() => {
// Access bindings via env
// For example: env.MY_KV, env.MY_BUCKET, env.AI, etc.
});
function RouteComponent() {
// ...
}Wrangler 設定に基づいて、バインディングの TypeScript 型を生成します。
npm run cf-typegenyarn run cf-typegenpnpm run cf-typegenバインディングを使うと、アプリケーションを Cloudflare Developer Platform と完全に統合でき、コンピュート、ストレージ、AI などへアクセスできます。
バインディング
Wrangler 設定に R2 バケットバインディング を追加します。
{
"r2_buckets": [
{
"binding": "MY_BUCKET",
"bucket_name": "<YOUR_BUCKET_NAME>",
},
],
}[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "<YOUR_BUCKET_NAME>"サーバー関数からバケットにアクセスします。
import { createServerFn } from "@tanstack/react-start";
import { env } from "cloudflare:workers";
const uploadFile = createServerFn({ method: "POST" })
.validator((data) => data)
.handler(async ({ data }) => {
await env.MY_BUCKET.put(data.key, data.content);
return { success: true };
});
const getFile = createServerFn()
.validator((key) => key)
.handler(async ({ data: key }) => {
const object = await env.MY_BUCKET.get(key);
return object ? await object.text() : null;
});import { createServerFn } from "@tanstack/react-start";
import { env } from "cloudflare:workers";
const uploadFile = createServerFn({ method: "POST" })
.validator((data: { key: string; content: string }) => data)
.handler(async ({ data }) => {
await env.MY_BUCKET.put(data.key, data.content);
return { success: true };
});
const getFile = createServerFn()
.validator((key: string) => key)
.handler(async ({ data: key }) => {
const object = await env.MY_BUCKET.get(key);
return object ? await object.text() : null;
});ビルド時にアプリケーションを静的 HTML へプリレンダリングし、静的アセット として配信します。
import { defineConfig } from "vite";
import { cloudflare } from "@cloudflare/vite-plugin";
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [
cloudflare({ viteEnvironment: { name: "ssr" } }),
tanstackStart({
prerender: {
enabled: true,
},
}),
react(),
],
});import { defineConfig } from "vite";
import { cloudflare } from "@cloudflare/vite-plugin";
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [
cloudflare({ viteEnvironment: { name: "ssr" } }),
tanstackStart({
prerender: {
enabled: true,
},
}),
react(),
],
});ほかのオプションは TanStack Start の静的プリレンダリング ↗ を参照してください。
本番データを使ってプリレンダリングするには、リモートバインディング を使います。
CI 環境では、ビルド中に環境変数やシークレットが使えないことがあります。使えるようにするには、次のいずれかを行います。
- CI 環境で
CLOUDFLARE_INCLUDE_PROCESS_ENV=trueを設定し、必要な値を環境変数として渡します。 - Workers Builds を使っている場合は、ビルド設定 を更新します。