mcpField
C
cloudflare-full-stack-integration

cloudflare-full-stack-integration

github.com/jackspace开发1648 次安装12 周前更新
代码仓库

关于 cloudflare-full-stack-integration

面向 React 与 Cloudflare Workers 全栈应用的集成技能,涵盖 Hono 后端、Clerk 身份验证及相关配置。它提供前后端模板和逐步指南,重点处理令牌传递、CORS、身份加载时序与 D1 访问。

主要功能

  1. 01自动附加令牌的 API 客户端模板
  2. 02Clerk JWT 身份验证中间件
  3. 03CORS 中间件及路由顺序指导
  4. 04Workers、Vite 与环境变量配置
  5. 05D1 绑定访问与参数化查询模式
  6. 06身份加载和受保护路由模式

适用场景

  1. 01搭建 React 与 Workers API 集成
  2. 02为 API 路由配置 Clerk 身份验证
  3. 03排查 CORS 或身份加载导致的请求错误
  4. 04在 Workers 路由中安全访问 D1

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jackspace/claudeskillz --skill cloudflare-full-stack-integration

安装后在 Claude Code 中输入/cloudflare-full-stack-integration确认已加载。

附带文件README.mdSKILL.json

详细介绍

Cloudflare 全栈集成模式

经过生产环境验证的 React + Cloudflare Workers + Hono + Clerk 身份验证模式。

何时使用此技能

在以下情况下使用此技能:

  • 将 React 前端连接到 Cloudflare Worker 后端
  • 在全栈应用中使用 Clerk 实现身份验证
  • 设置自动包含身份验证令牌的 API 调用
  • 修复前端与后端之间的 CORS 错误
  • 防止身份验证加载时出现竞态条件
  • 正确配置环境变量
  • 设置从 API 路由访问 D1 数据库
  • 创建需要身份验证的受保护路由

此技能提供的内容

模板

前端(templates/frontend/):

  • lib/api-client.ts - 自动附加令牌的 Fetch 封装
  • components/ProtectedRoute.tsx - 带加载状态的身份验证门控模式

后端(templates/backend/):

  • middleware/cors.ts - 用于开发和生产环境的 CORS 配置
  • middleware/auth.ts - 使用 Clerk 进行 JWT 验证
  • routes/api.ts - 集成所有模式的 API 路由示例

配置(templates/config/):

  • wrangler.jsonc - 带绑定项的完整 Workers 配置
  • .dev.vars.example - 环境变量设置
  • vite.config.ts - Cloudflare Vite 插件配置

参考资料(references/):

  • common-race-conditions.md - 身份验证加载问题完整指南

关键架构见解

1. @cloudflare/vite-plugin 在同一个端口上运行

关键见解:开发期间,Worker 和前端在同一个端口上运行。

// ✅ CORRECT: Use relative URLs
fetch('/api/data')

// ❌ WRONG: Don't use absolute URLs or proxy
fetch('http://localhost:8787/api/data')

原因:Vite 插件直接在开发服务器中使用 workerd 运行 Worker。无需代理!

2. 必须在路由之前应用 CORS
// ✅ CORRECT ORDER
app.use('/api/*', cors())
app.post('/api/data', handler)

// ❌ WRONG ORDER - Will cause CORS errors
app.post('/api/data', handler)
app.use('/api/*', cors())
3. 身份验证加载不是竞态条件

大多数“竞态条件”实际上是缺少 isLoaded 检查:

// ❌ WRONG: Calls API before token ready
useEffect(() => {
  fetch('/api/data') // 401 error!
}, [])

// ✅ CORRECT: Wait for auth to load
const { isLoaded, isSignedIn } = useSession()
useEffect(() => {
  if (!isLoaded || !isSignedIn) return
  fetch('/api/data') // Now token is ready
}, [isLoaded, isSignedIn])
4. 环境变量有不同的规则

前端(Vite):

  • 必须以 VITE_ 前缀开头
  • 在 .env 文件中定义
  • 访问方式:import.meta.env.VITE_VARIABLE_NAME

后端(Workers):

  • 无需前缀
  • 在 .dev.vars 文件(开发环境)或 Wrangler 密钥(生产环境)中定义
  • 访问方式:env.VARIABLE_NAME
5. D1 绑定项始终可用

通过绑定项访问 D1,无需管理连接:

// ✅ CORRECT: Direct access via binding
const { results } = await env.DB.prepare('SELECT * FROM users').run()

// ❌ WRONG: No need to "connect" first
const connection = await env.DB.connect() // This doesn't exist!

分步集成指南

步骤 1:项目设置
# Create project with Cloudflare Workers + React
npm create cloudflare@latest my-app
cd my-app

# Install dependencies
npm install hono @clerk/clerk-react @clerk/backend
npm install -D @cloudflare/vite-plugin @tailwindcss/vite
步骤 2:配置 Vite

将 templates/config/vite.config.ts 复制到项目根目录。

要点:

  • 包含 cloudflare() 插件
  • 无需代理配置
  • 设置路径别名,以便简洁地导入
步骤 3:配置 Wrangler

将 templates/config/wrangler.jsonc 复制到项目根目录。

更新:

  • 将 name 替换为你的应用名称
  • 根据需要添加 D1/KV/R2 绑定项
  • 为 API 路由设置 run_worker_first: ["/api/*"]
步骤 4:设置环境变量

创建 .dev.vars(已加入 gitignore):

CLERK_PUBLISHABLE_KEY=pk_test_xxxxx
CLERK_SECRET_KEY=sk_test_xxxxx

为前端创建 .env:

VITE_CLERK_PUBLISHABLE_KEY=pk_test_xxxxx
步骤 5:添加 CORS 中间件

将 templates/backend/middleware/cors.ts 复制到后端。

在主 Worker 文件中应用:

import { corsMiddleware } from './middleware/cors'

app.use('/api/*', (c, next) => corsMiddleware(c.env)(c, next))

重要:务必在定义路由之前应用此中间件!

步骤 6:添加身份验证中间件

将 templates/backend/middleware/auth.ts 复制到后端。

应用于受保护的路由:

import { jwtAuthMiddleware } from './middleware/auth'

app.use('/api/protected/*', jwtAuthMiddleware(c.env.CLERK_SECRET_KEY))
步骤 7:设置 API 客户端

将 templates/frontend/lib/api-client.ts 复制到前端。

在 App 组件中使用:

import { useApiClient } from '@/lib/api-client'

function App() {
  useApiClient() // Set up token access
  return <YourApp />
}
步骤 8:创建受保护路由

复制 templates/frontend/components/ProtectedRoute.tsx。

用于包裹需要身份验证的页面:

<ProtectedRoute>
  <Dashboard />
</ProtectedRoute>
步骤 9:创建 API 路由

将 templates/backend/routes/api.ts 作为参考。

所有路由的模式:

  1. 首先应用 CORS
  2. 将身份验证中间件应用于受保护的路由
  3. 从 JWT 负载中提取用户 ID
  4. 通过 env 绑定项访问 D1/KV/R2
  5. 返回带类型的 JSON 响应
步骤 10:测试集成
# Start dev server
npm run dev

# Both frontend and backend run on http://localhost:5173
# API routes: http://localhost:5173/api/*
# Frontend: http://localhost:5173/*

常见问题及解决方案

问题:401 未授权错误

症状:用户已登录,但 API 调用仍返回 401

原因:Clerk 会话加载完成前就调用了 API

解决方法:调用 API 前检查 isLoaded 和 isSignedIn

const { isLoaded, isSignedIn } = useSession()
if (!isLoaded || !isSignedIn) return // Wait for auth

参见:references/common-race-conditions.md

问题:CORS 错误

症状:出现“No 'Access-Control-Allow-Origin' header”错误

原因:

  1. 未应用 CORS 中间件
  2. 在路由之后应用了 CORS 中间件(顺序错误)
  3. 生产环境中未允许该来源

解决方法:

// Apply BEFORE routes
app.use('/api/*', cors())
app.post('/api/data', handler)

对于生产环境,请使用你的域名更新 corsProdMiddleware。

问题:环境变量不起作用

症状:前端或后端中的变量为 undefined

前端解决方法:

  • 变量必须以 VITE_ 开头
  • 必须放在 .env 文件中(而不是 .dev.vars)
  • 通过 import.meta.env.VITE_NAME 访问

后端解决方法:

  • 本地开发时,将变量放在 .dev.vars 中
  • 生产环境使用 wrangler secret put NAME
  • 通过 env.NAME 访问
问题:D1 查询失败

症状:数据库查询报错

原因:

  1. 未在 wrangler.jsonc 中配置绑定
  2. SQL 语法错误
  3. 未使用参数化查询

解决方法:

// ✅ CORRECT: Parameterized query
await env.DB.prepare('SELECT * FROM users WHERE id = ?')
  .bind(userId)
  .run()

// ❌ WRONG: SQL injection risk
await env.DB.prepare(`SELECT * FROM users WHERE id = ${userId}`).run()
问题:请求未附带令牌

症状:后端收到的请求不含 Authorization 标头

原因:未使用 apiClient 或未调用 useApiClient() 钩子

解决方法:

  1. 在 App 组件中调用 useApiClient()
  2. 使用 apiClient.get(),而不是原始的 fetch()
// In App.tsx
import { useApiClient } from '@/lib/api-client'
function App() {
  useApiClient() // MUST call this
  return <YourApp />
}

// In components
import { apiClient } from '@/lib/api-client'
const data = await apiClient.get('/api/data')

集成检查清单

部署前,请确认:

前端:

  • 已在 App 组件中调用 useApiClient()
  • 所有受保护页面均已用 <ProtectedRoute> 包装
  • 发起 API 调用前检查 isLoaded
  • 环境变量以 VITE_ 开头
  • 所有 API 调用均使用 apiClient

后端:

  • 在路由之前应用 CORS 中间件
  • 在 /api/protected/* 路由上应用身份验证中间件
  • 环境变量位于 .dev.vars(开发环境)和密钥(生产环境)中
  • 已在 wrangler.jsonc 中配置 D1/KV/R2 绑定
  • 对 D1 使用参数化查询

配置:

  • wrangler.jsonc 中的绑定配置正确
  • vite.config.ts 包含 cloudflare() 插件
  • .dev.vars 文件存在且已加入 gitignore
  • .env 文件存在,用于存放前端变量
  • wrangler.jsonc 中设置了 run_worker_first: ["/api/*"]

软件包版本(已于 2025-10-23 验证)

所有软件包均为当前稳定版本:

{
  "@clerk/clerk-react": "5.53.3",
  "@clerk/backend": "2.19.0",
  "hono": "4.10.2",
  "vite": "7.1.11",
  "@cloudflare/vite-plugin": "1.13.14"
}

官方文档链接

生产环境验证

已在以下项目中测试这些模式:

令牌效率

不使用此技能:约 12k 个令牌 + 2–4 个集成错误 使用此技能:约 4k 个令牌 + 0 个错误 节省:约 67% 的令牌,100% 避免错误


请记住:大多数集成问题都只是漏掉了 isLoaded 检查,或中间件顺序错误。请使用模板并遵循分步指南!

评论

支持 Markdown