TL;DR: 将 TanStack Start 应用部署到 Cloudflare Workers,需要精细配置
wrangler.jsonc、跨开发和生产环境管理环境变量、配置 D1 数据库及自动化迁移、集成 R2 对象存储,并搭建可靠的 CI/CD 流水线。本指南涵盖从脚手架搭建到生产监控的每一步,助你在 Cloudflare 边缘网络上自信交付。
引言:为什么选择 Cloudflare Workers 部署 TanStack Start
TanStack Start 是构建在 Vinxi 之上的全栈 React 框架,将服务端渲染、流式传输和静态生成带入 TanStack 生态。在部署层面,Cloudflare Workers 为 Start 应用提供了极具吸引力的运行时选择。
与需要冷启动、区域固定和手动扩缩容的传统 Node.js 服务器不同,Cloudflare Workers 基于 V8 isolate 运行在全球 330+ 个位置。这意味着你的 TanStack Start 应用可以从边缘向每位用户就近提供初始 HTML、流式内容更新和处理 API 请求。
但这种架构转变也带来了新的配置挑战。Workers 运行时不支持 Node.js API(如 fs、net、child_process)。构建流水线、环境变量和数据库连接都需要进行适配。本指南将详细介绍我们大规模运行 TanStack Start on Cloudflare Workers 所用的生产就绪配置。
wrangler.jsonc 深度配置
wrangler.jsonc 是 Cloudflare 部署的单一真相来源。以下是我们使用的生产配置,并附有详细注解:
{
"$schema": "https://raw.githubusercontent.com/cloudflare/workers-sdk/main/packages/wrangler/config-schema.json",
"name": "tanstack-ship",
"main": "./dist/worker.js",
"compatibility_date": "2026-05-01",
"compatibility_flags": ["nodejs_compat"],
"assets": {
"directory": "./dist/public",
"binding": "ASSETS",
"html_handling": "auto",
"not_found_handling": "404"
},
"workers_dev": false,
"route": {
"pattern": "tanstack-ship.com",
"custom_domain": true,
"zone_id": "YOUR_ZONE_ID"
},
"d1_databases": [
{
"binding": "DB",
"database_name": "tanstack-ship-db",
"database_id": "YOUR_D1_DATABASE_ID",
"migrations_dir": "./migrations"
}
],
"r2_buckets": [
{
"binding": "R2",
"bucket_name": "tanstack-ship-assets"
}
],
"vars": {
"APP_VERSION": "1.0.0",
"SENTRY_DSN": ""
},
"env": {
"production": {
"vars": {
"SENTRY_DSN": "https://your-sentry-dsn@o123.ingest.sentry.io/456"
},
"routes": [
{
"pattern": "tanstack-ship.com",
"custom_domain": true
}
]
},
"preview": {
"workers_dev": true,
"vars": {
"SENTRY_DSN": ""
}
}
},
"observability": {
"enabled": true,
"head_sampling_rate": 0.1
}
}
关键字段说明
compatibility_flags:nodejs_compat标志启用部分 Node.js API(如Buffer、process.env)。许多 npm 包依赖这些 API,请务必保持此标志开启。assets:html_handling: "auto"指示 Workers 对目录请求返回index.html——这对客户端路由兜底至关重要。not_found_handling: "404"确保未知路径返回正确的 404。env块:定义环境特定覆盖。preview环境使用workers_dev: true以适配*.workers.dev子域名,而production则绑定自定义域名。
环境变量:开发 vs 生产
本地开发
在项目根目录创建 .dev.vars 文件:
# .dev.vars — 由 wrangler dev 加载
SENTRY_DSN=
STRIPE_SECRET_KEY=your-stripe-secret-key
RESEND_API_KEY=your-resend-api-key
PUBLIC_SITE_URL=http://localhost:5173
Cloudflare 的 wrangler dev 命令会自动读取 .dev.vars 并将其注入 Worker 运行时。
生产密钥
对于生产密钥,请使用 wrangler secret put 将敏感值与配置文件隔离:
npx wrangler secret put SENTRY_DSN
npx wrangler secret put STRIPE_SECRET_KEY
密钥在静态时加密,在边缘运行时注入。它们不会出现在 wrangler.jsonc 的 vars 区段中——这是常见的安全错误。
类型安全的访问模式
将所有环境变量访问集中到一个模块中,并使用 Zod 进行运行时验证:
// src/env.ts
import { z } from "zod";
const envSchema = z.object({
SENTRY_DSN: z.string().optional(),
STRIPE_SECRET_KEY: z.string().min(1),
RESEND_API_KEY: z.string().min(1),
PUBLIC_SITE_URL: z.string().url().default("http://localhost:5173"),
DB: z.any(), // D1 binding
R2: z.any(), // R2 binding
ASSETS: z.any(), // Assets binding
});
export type Env = z.infer<typeof envSchema>;
export function parseEnv(env: Record<string, unknown>): Env {
const result = envSchema.safeParse(env);
if (!result.success) {
console.error("Invalid environment variables:", result.error.flatten());
throw new Error("Environment validation failed");
}
return result.data;
}
此模式提供运行时类型安全,并在 CI 早期阶段捕获配置错误的环境。
D1 数据库配置与迁移
1. 创建数据库
npx wrangler d1 create tanstack-ship-db
将返回的 database_id 复制到 wrangler.jsonc 中。
2. 编写迁移
将 SQL 迁移文件放在 migrations/ 目录中:
-- migrations/0001_users.sql
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX idx_users_email ON users(email);
3. 应用迁移
本地:
npx wrangler d1 migrations apply tanstack-ship-db --local
生产:
npx wrangler d1 migrations apply tanstack-ship-db --remote
4. CI 中的自动化迁移
# .github/workflows/deploy.yml(节选)
- name: Apply D1 Migrations
run: npx wrangler d1 migrations apply tanstack-ship-db --remote
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
在部署新版本 Worker 之前运行迁移,实现零停机时间部署。
R2 对象存储集成
在 wrangler.jsonc 中添加 R2 绑定后,配置客户端以处理文件上传和获取:
// src/lib/r2-client.ts
import type { R2Bucket } from "@cloudflare/workers-types";
let bucket: R2Bucket;
export function initR2(r2: R2Bucket) {
bucket = r2;
}
export async function uploadFile(
key: string,
body: ReadableStream | ArrayBuffer,
contentType: string
) {
return bucket.put(key, body, {
httpMetadata: { contentType },
customMetadata: { uploadedAt: new Date().toISOString() },
});
}
export async function getFile(key: string) {
const object = await bucket.get(key);
if (!object) return null;
return object;
}
生产环境优化
缓存响应头
function setCachingHeaders(response: Response, pathname: string): Response {
const headers = new Headers(response.headers);
// 静态资源:长期缓存
if (/\.(js|css|png|jpg|webp|svg|woff2?)$/i.test(pathname)) {
headers.set("Cache-Control", "public, max-age=31536000, immutable");
}
// HTML 页面:短期 CDN 缓存,浏览器不缓存
else if (pathname.endsWith(".html") || !pathname.includes(".")) {
headers.set("Cache-Control", "public, s-maxage=60, stale-while-revalidate=600");
}
return new Response(response.body, {
status: response.status,
headers,
});
}
启用流式传输
// wrangler.jsonc
{
"compatibility_flags": ["nodejs_compat"],
"streaming": true
}
启用流式传输后,Suspense 边界可以逐步发送内容,改善用户感知的加载性能。
CI/CD 流水线配置
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
- run: npm ci
- run: npm run typecheck
- run: npm run lint
- run: npm run build
env:
PUBLIC_SITE_URL: ${{ vars.PUBLIC_SITE_URL }}
- name: Apply D1 Migrations
run: npx wrangler d1 migrations apply tanstack-ship-db --remote
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
- name: Deploy to Cloudflare Workers
run: npx wrangler deploy --env production
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
常见部署问题及解决方案
-
Node.js 内置模块 "Module not found":启用
nodejs_compat标志。若仍然报错,请寻找 Workers 兼容的替代方案。 -
D1 迁移报 "Table already exists":始终使用
CREATE TABLE IF NOT EXISTS和CREATE INDEX IF NOT EXISTS。 -
刷新时客户端路由返回 404:确认
wrangler.jsonc中设置了html_handling: "auto"。 -
环境变量在运行时未定义:将密钥迁移至
wrangler secret put,vars区段仅用于非敏感配置。 -
打包体积超过 1MB 限制:确保 Vite 构建进行了 tree-shaking。对重型依赖使用动态
import()。
结语
将 TanStack Start 部署到 Cloudflare Workers,是交付全栈 React 应用最高性能且最具性价比的方式之一。边缘运行时带来全球分发、即时冷启动和慷慨的免费额度。
核心要点:
- 使用 Zod 在边缘验证环境变量,在任何逻辑运行之前。
- 在部署之前运行迁移,而非之后。
- 积极但审慎地设置缓存响应头——HTML 使用
s-maxage,静态资源使用immutable。 - 尽早启用可观测性——出现问题时你会需要这些链路追踪。
如需亲手实践完整应用的构建流程,请参阅 TanStack Start 端到端教程。如需将 D1 数据库推至生产,请阅读 边缘数据库:Cloudflare D1 生产实践。官方参考请查阅 Wrangler CLI、Cloudflare D1 和 R2 文档。