mcpField
C
cloudflare-worker-base

cloudflare-worker-base

github.com/jackspace云与 DevOps1639 次安装12 周前更新
代码仓库

关于 cloudflare-worker-base

cloudflare-worker-base 是面向 Cloudflare Workers 开发者的项目搭建技能,提供基于 Hono、Vite 和 Wrangler 的配置步骤与模板,并说明常见问题的规避方法。

主要功能

  1. 01提供 Workers 项目搭建步骤
  2. 02配置 Hono、Vite 与 Wrangler
  3. 03包含配置文件和应用模板
  4. 04说明路由、静态资源与 API 设置
  5. 05整理开发、类型生成和部署流程
  6. 06列出已知问题及规避方法

适用场景

  1. 01从头创建 Cloudflare Worker 项目
  2. 02搭建含 API 路由和静态页面的应用
  3. 03配置本地开发和类型生成
  4. 04排查路由冲突或部署问题

安装

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

$npx skills add https://github.com/jackspace/claudeskillz --skill cloudflare-worker-base

安装后在 Claude Code 中输入/cloudflare-worker-base确认已加载。

附带文件README.mdSKILL.json

详细介绍

Cloudflare Worker 基础技术栈

已通过生产环境测试:cloudflare-worker-base-test (https://cloudflare-worker-base-test.webfonts.workers.dev) 最后更新:2025-10-20 状态:已准备好投入生产 ✅


快速开始(5 分钟)

1. 搭建项目
npm create cloudflare@latest my-worker -- \
  --type hello-world \
  --ts \
  --git \
  --deploy false \
  --framework none

这些标志的作用:

  • --type hello-world:简洁的起点
  • --ts:支持 TypeScript
  • --git:初始化 git 仓库
  • --deploy false:暂不部署(先进行配置)
  • --framework none:我们会自行添加 Vite
2. 安装依赖项
cd my-worker
npm install [email protected]
npm install -D @cloudflare/[email protected] vite@latest

版本说明:

  • [email protected]:最新稳定版(已于 2025-10-20 验证)
  • @cloudflare/[email protected]:最新稳定版,修复 HMR 竞态条件
  • vite:与 Cloudflare 插件兼容的最新版本
3. 配置 Wrangler

创建或更新 wrangler.jsonc:

{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "my-worker",
  "main": "src/index.ts",
  "account_id": "YOUR_ACCOUNT_ID",
  "compatibility_date": "2025-10-11",
  "observability": {
    "enabled": true
  },
  "assets": {
    "directory": "./public/",
    "binding": "ASSETS",
    "not_found_handling": "single-page-application",
    "run_worker_first": ["/api/*"]
  }
}

重要:run_worker_first 配置

  • 如果不配置,SPA 回退机制会拦截 API 路由
  • API 路由会返回 index.html,而不是 JSON
  • 来源:workers-sdk #8879
4. 配置 Vite

创建 vite.config.ts:

import { defineConfig } from 'vite'
import { cloudflare } from '@cloudflare/vite-plugin'

export default defineConfig({
  plugins: [
    cloudflare({
      // Optional: Configure the plugin if needed
    }),
  ],
})

使用 @cloudflare/vite-plugin 的原因:

  • Cloudflare 官方插件
  • 支持 Workers HMR
  • 支持使用 Miniflare 进行本地开发
  • 1.13.13 版本修复了 “A hanging Promise was canceled” 错误

四步设置流程

第 1 步:创建包含 API 路由的 Hono 应用

创建 src/index.ts:

/**
 * Cloudflare Worker with Hono
 *
 * CRITICAL: Export pattern to prevent build errors
 * ✅ CORRECT: export default app
 * ❌ WRONG:   export default { fetch: app.fetch }
 */

import { Hono } from 'hono'

// Type-safe environment bindings
type Bindings = {
  ASSETS: Fetcher
}

const app = new Hono<{ Bindings: Bindings }>()

/**
 * API Routes
 * Handled BEFORE static assets due to run_worker_first config
 */
app.get('/api/hello', (c) => {
  return c.json({
    message: 'Hello from Cloudflare Workers!',
    timestamp: new Date().toISOString(),
  })
})

app.get('/api/health', (c) => {
  return c.json({
    status: 'ok',
    version: '1.0.0',
    environment: c.env ? 'production' : 'development',
  })
})

/**
 * Fallback to Static Assets
 * Any route not matched above is served from public/ directory
 */
app.all('*', (c) => {
  return c.env.ASSETS.fetch(c.req.raw)
})

/**
 * Export the Hono app directly (ES Module format)
 * This is the correct pattern for Cloudflare Workers with Hono + Vite
 */
export default app

使用此导出模式的原因:

  • 来源:honojs/hono #3955
  • 使用 { fetch: app.fetch } 会导致:“Cannot read properties of undefined (reading 'map')”
  • 例外:如果需要 scheduled/tail 处理程序,请使用 Module Worker 格式:
    export default {
      fetch: app.fetch,
      scheduled: async (event, env, ctx) => { /* ... */ }
    }
    
第 2 步:创建静态前端

创建 public/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Worker App</title>
  <link rel="stylesheet" href="/styles.css">
</head>
<body>
  <div class="container">
    <h1>Cloudflare Worker + Static Assets</h1>
    <button onclick="testAPI()">Test API</button>
    <pre id="output"></pre>
  </div>
  <script src="/script.js"></script>
</body>
</html>

创建 public/script.js:

async function testAPI() {
  const response = await fetch('/api/hello')
  const data = await response.json()
  document.getElementById('output').textContent = JSON.stringify(data, null, 2)
}

创建 public/styles.css:

body {
  font-family: system-ui, -apple-system, sans-serif;
  max-width: 800px;
  margin: 40px auto;
  padding: 20px;
}

button {
  background: #0070f3;
  color: white;
  border: none;
  padding: 12px 24px;
  border-radius: 6px;
  cursor: pointer;
}

pre {
  background: #f5f5f5;
  padding: 16px;
  border-radius: 6px;
  overflow-x: auto;
}
第 3 步:更新 Package 脚本

更新 package.json:

{
  "scripts": {
    "dev": "wrangler dev",
    "deploy": "wrangler deploy",
    "cf-typegen": "wrangler types"
  }
}
第 4 步:测试并部署
# Generate TypeScript types for bindings
npm run cf-typegen

# Start local dev server (http://localhost:8787)
npm run dev

# Deploy to production
npm run deploy

预防已知问题

此技能可预防 6 个已记录的问题:

问题 #1:导出语法错误

错误:“Cannot read properties of undefined (reading 'map')” 来源:honojs/hono #3955 预防方法:使用 export default app(不要使用 { fetch: app.fetch })

问题 #2:静态资源路由冲突

错误:API 路由返回 index.html,而不是 JSON 来源:workers-sdk #8879 预防方法:将 "run_worker_first": ["/api/*"] 添加到 wrangler.jsonc

问题 #3:未导出 Scheduled/Cron

错误:“Handler does not export a scheduled() function” 来源:honojs/vite-plugins #275 预防方法:需要时使用 Module Worker 格式:

export default {
  fetch: app.fetch,
  scheduled: async (event, env, ctx) => { /* ... */ }
}
问题 #4:HMR 竞态条件

错误:开发期间出现 “A hanging Promise was canceled” 来源:workers-sdk #9518 预防方法:使用 @cloudflare/[email protected] 或更高版本

问题 #5:静态资源上传竞态

错误:CI/CD 中出现非确定性的部署失败 来源:workers-sdk #7555 预防方法:使用带重试逻辑的 Wrangler 4.x+(近期版本已修复)

问题 #6:混淆 Service Worker 格式

错误:使用已弃用的 Service Worker 格式 来源:Cloudflare 迁移指南 预防方法:始终使用 ES Module 格式(见第 1 步)


配置文件参考

wrangler.jsonc(完整示例)
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "my-worker",
  "main": "src/index.ts",
  "account_id": "YOUR_ACCOUNT_ID",
  "compatibility_date": "2025-10-11",
  "observability": {
    "enabled": true
  },
  "assets": {
    "directory": "./public/",
    "binding": "ASSETS",
    "not_found_handling": "single-page-application",
    "run_worker_first": ["/api/*"]
  }
  /* Optional: Environment Variables */
  // "vars": { "MY_VARIABLE": "production_value" }

  /* Optional: KV Namespace Bindings */
  // "kv_namespaces": [
  //   { "binding": "MY_KV", "id": "YOUR_KV_ID" }
  // ]

  /* Optional: D1 Database Bindings */
  // "d1_databases": [
  //   { "binding": "DB", "database_name": "my-db", "database_id": "YOUR_DB_ID" }
  // ]

  /* Optional: R2 Bucket Bindings */
  // "r2_buckets": [
  //   { "binding": "MY_BUCKET", "bucket_name": "my-bucket" }
  // ]
}

使用 wrangler.jsonc 而非 wrangler.toml 的原因:

  • 自 Wrangler v3.91.0 起,优先使用 JSON 格式
  • 使用 JSON schema 可获得更好的 IDE 支持
  • JSONC 允许注释
vite.config.ts(完整示例)
import { defineConfig } from 'vite'
import { cloudflare } from '@cloudflare/vite-plugin'

export default defineConfig({
  plugins: [
    cloudflare({
      // Persist state between HMR updates
      persist: true,
    }),
  ],

  // Optional: Configure server
  server: {
    port: 8787,
  },

  // Optional: Build optimizations
  build: {
    target: 'esnext',
    minify: true,
  },
})
tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "lib": ["ES2022"],
    "moduleResolution": "bundler",
    "types": ["@cloudflare/workers-types/2023-07-01"],
    "resolveJsonModule": true,
    "allowJs": true,
    "checkJs": false,
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "isolatedModules": true,
    "noEmit": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

API 路由模式

基本 JSON 响应
app.get('/api/users', (c) => {
  return c.json({
    users: [
      { id: 1, name: 'Alice' },
      { id: 2, name: 'Bob' }
    ]
  })
})
使用请求正文的 POST
app.post('/api/users', async (c) => {
  const body = await c.req.json()

  // Validate and process body
  return c.json({ success: true, data: body }, 201)
})
路由参数
app.get('/api/users/:id', (c) => {
  const id = c.req.param('id')
  return c.json({ id, name: 'User' })
})
查询参数
app.get('/api/search', (c) => {
  const query = c.req.query('q')
  return c.json({ query, results: [] })
})
错误处理
app.get('/api/data', async (c) => {
  try {
    // Your logic here
    return c.json({ success: true })
  } catch (error) {
    return c.json({ error: error.message }, 500)
  }
})
使用绑定(KV、D1、R2)
type Bindings = {
  ASSETS: Fetcher
  MY_KV: KVNamespace
  DB: D1Database
  MY_BUCKET: R2Bucket
}

const app = new Hono<{ Bindings: Bindings }>()

app.get('/api/data', async (c) => {
  // KV
  const value = await c.env.MY_KV.get('key')

  // D1
  const result = await c.env.DB.prepare('SELECT * FROM users').all()

  // R2
  const object = await c.env.MY_BUCKET.get('file.txt')

  return c.json({ value, result, object })
})

静态资源最佳实践

目录结构
public/
├── index.html          # Main entry point
├── styles.css          # Global styles
├── script.js           # Client-side JavaScript
├── favicon.ico         # Favicon
└── assets/             # Images, fonts, etc.
    ├── logo.png
    └── fonts/
SPA 回退

"not_found_handling": "single-page-application" 配置表示:

  • 未知路由会返回 index.html
  • 适用于 React Router、Vue Router 等
  • 但是,API 路由需要设置 run_worker_first!
路由优先级

设置 "run_worker_first": ["/api/*"] 后:

  1. /api/hello → Worker 处理(返回 JSON)
  2. / → 静态资源提供 index.html
  3. /styles.css → 静态资源提供 styles.css
  4. /unknown → 静态资源提供 index.html(SPA 回退)
缓存静态资源

静态资源会自动在边缘缓存。要清除缓存:

<link rel="stylesheet" href="/styles.css?v=1.0.0">
<script src="/script.js?v=1.0.0"></script>

开发工作流

本地开发
npm run dev
  • 服务器运行于 http://localhost:8787
  • 已启用 HMR(文件更改后会自动重新加载)
  • 使用 Miniflare 进行本地模拟
  • 所有绑定都可在本地使用(KV、D1、R2)
测试 API 路由
# Test GET endpoint
curl http://localhost:8787/api/hello

# Test POST endpoint
curl -X POST http://localhost:8787/api/echo \
  -H "Content-Type: application/json" \
  -d '{"test": "data"}'
类型生成
npm run cf-typegen

生成包含以下内容的 worker-configuration.d.ts:

  • 绑定类型(KV、D1、R2 等)
  • 环境变量类型
  • 在编辑器中提供自动补全
部署
# Deploy to production
npm run deploy

# Deploy to specific environment
wrangler deploy --env staging

# Tail logs in production
wrangler tail

# Check deployment status
wrangler deployments list

完整设置清单

  • 使用 npm create cloudflare@latest 搭建项目框架
  • 已安装依赖:[email protected]、@cloudflare/[email protected]
  • 已创建 wrangler.jsonc,其中:
    • account_id 已设为你的 Cloudflare 账户
    • assets.directory 指向 ./public/
    • assets.run_worker_first 包含 /api/*
    • compatibility_date 已设为近期日期
  • 已创建包含 @cloudflare/vite-plugin 的 vite.config.ts
  • 已创建包含 Hono 应用的 src/index.ts
    • 使用 export default app(不要使用 { fetch: app.fetch })
    • 包含 ASSETS 绑定类型
    • 具有回退路由:app.all('*', (c) => c.env.ASSETS.fetch(c.req.raw))
  • 已创建 public/ 目录并放入静态文件
  • 已成功执行 npm run cf-typegen
  • npm run dev 可无错误地启动
  • 已在浏览器/curl 中测试 API 路由
  • 静态资源可正常提供
  • HMR 可正常运行,不会崩溃
  • 已准备好使用 npm run deploy 进行部署

高级主题

添加中间件
import { Hono } from 'hono'
import { logger } from 'hono/logger'
import { cors } from 'hono/cors'

const app = new Hono<{ Bindings: Bindings }>()

// Global middleware
app.use('*', logger())
app.use('/api/*', cors())

// Route-specific middleware
app.use('/admin/*', async (c, next) => {
  // Auth check
  await next()
})
特定环境的配置
// wrangler.jsonc
{
  "name": "my-worker",
  "env": {
    "staging": {
      "vars": { "ENV": "staging" }
    },
    "production": {
      "vars": { "ENV": "production" }
    }
  }
}

部署:wrangler deploy --env staging

自定义错误页面
app.onError((err, c) => {
  console.error(err)
  return c.json({ error: 'Internal Server Error' }, 500)
})

app.notFound((c) => {
  return c.json({ error: 'Not Found' }, 404)
})
使用 Vitest 进行测试
npm install -D vitest @cloudflare/vitest-pool-workers

创建 vitest.config.ts:

import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    poolOptions: {
      workers: {
        wrangler: { configPath: './wrangler.jsonc' },
      },
    },
  },
})

完整测试指南请参阅 reference/testing.md。


文件模板

所有模板均位于 templates/ 目录中:

  • wrangler.jsonc - 完整的 Worker 配置
  • vite.config.ts - Vite + Cloudflare 插件设置
  • package.json - 依赖和脚本
  • tsconfig.json - TypeScript 配置
  • src/index.ts - 包含 API 路由的 Hono 应用
  • public/index.html - 静态前端示例
  • public/styles.css - 样式示例
  • public/script.js - API 测试函数

将这些文件复制到项目中,并根据需要进行自定义。


参考文档

深入了解请参阅:

  • architecture.md - 深入讲解导出模式、路由和静态资源
  • common-issues.md - 详细排查全部 6 个问题
  • deployment.md - Wrangler 命令、CI/CD 模式和生产环境提示

官方文档


依赖(最近验证于 2025-10-20)

{
  "dependencies": {
    "hono": "^4.10.1"
  },
  "devDependencies": {
    "@cloudflare/vite-plugin": "^1.13.13",
    "@cloudflare/workers-types": "^4.20251011.0",
    "vite": "^7.0.0",
    "wrangler": "^4.43.0",
    "typescript": "^5.9.0"
  }
}

生产示例

此技能基于 cloudflare-worker-base-test 项目:

此技能中的所有模式均已在生产环境中验证。


有疑问?遇到问题?

  1. 先查看 reference/common-issues.md
  2. 确认已完成 4 步设置流程中的所有步骤
  3. 确认使用 export default app(而不是 { fetch: app.fetch })
  4. 确认已配置 run_worker_first
  5. 查看官方文档:https://developers.cloudflare.com/workers/

评论

支持 Markdown