cloudflare
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCloudflare Developer Platform Skill
Cloudflare开发者平台技能指南
Cloudflare Developer Platform is a comprehensive edge computing ecosystem for building full-stack applications on Cloudflare's global network. It includes serverless functions, databases, storage, AI/ML capabilities, and static site hosting.
Cloudflare开发者平台是一套全面的边缘计算生态系统,用于在Cloudflare全球网络上构建全栈应用。它包含无服务器函数、数据库、存储、AI/ML能力以及静态站点托管服务。
When to Use This Skill
何时使用本技能
Use this skill when:
- Building serverless applications on the edge
- Implementing edge databases (D1 SQLite)
- Working with object storage (R2) or key-value stores (KV)
- Creating real-time applications with WebSockets (Durable Objects)
- Integrating AI/ML capabilities (Workers AI, AI Gateway, Agents)
- Deploying static sites with serverless functions (Pages)
- Building full-stack applications with frameworks (Next.js, Remix, Astro, etc.)
- Implementing message queues and background jobs (Queues)
- Optimizing for global performance and low latency
在以下场景使用本技能:
- 在边缘构建无服务器应用
- 部署边缘数据库(D1 SQLite)
- 使用对象存储(R2)或键值存储(KV)
- 基于WebSocket创建实时应用(Durable Objects)
- 集成AI/ML功能(Workers AI、AI Gateway、Agents)
- 部署带有无服务器函数的静态站点(Pages)
- 使用框架构建全栈应用(Next.js、Remix、Astro等)
- 实现消息队列与后台任务(Queues)
- 优化全球性能与降低延迟
Core Concepts
核心概念
Edge Computing Platform
边缘计算平台
Cloudflare's Edge Network: Code runs on servers globally distributed across 300+ cities, executing requests from the nearest location for ultra-low latency.
Key Components:
- Workers: Serverless functions on the edge
- D1: SQLite database with global read replication
- KV: Distributed key-value store with eventual consistency
- R2: Object storage with zero egress fees
- Durable Objects: Stateful compute with WebSocket support
- Queues: Message queue system for async processing
- Pages: Static site hosting with serverless functions
- Workers AI: Run AI models on the edge
- AI Gateway: Unified interface for AI providers
Cloudflare边缘网络:代码运行在全球300+城市的分布式服务器上,从离用户最近的位置处理请求,实现超低延迟。
核心组件:
- Workers:边缘无服务器函数
- D1:支持全局读取复制的SQLite数据库
- KV:具有最终一致性的分布式键值存储
- R2:零出口费用的对象存储
- Durable Objects:支持WebSocket的有状态计算服务
- Queues:用于异步处理的消息队列系统
- Pages:带有无服务器函数的静态站点托管服务
- Workers AI:在边缘运行AI模型
- AI Gateway:AI提供商统一接口
Execution Model
执行模型
V8 Isolates: Lightweight execution environments (faster than containers) with:
- Millisecond cold starts
- Zero infrastructure management
- Automatic scaling
- Pay-per-request pricing
Handler Types:
- : HTTP requests
fetch - : Cron jobs
scheduled - : Message processing
queue - : Log aggregation
tail - : Email handling
email - : Durable Object timers
alarm
V8 Isolates:轻量级执行环境(比容器更快),具备:
- 毫秒级冷启动
- 无需基础设施管理
- 自动弹性扩容
- 按请求付费定价
处理器类型:
- :HTTP请求处理
fetch - :定时任务(Cron)
scheduled - :消息处理
queue - :日志聚合
tail - :邮件处理
email - :Durable Object定时器
alarm
API Key Configuration
API密钥配置
Cloudflare skills require API credentials for authentication. The system searches for API keys in this order:
- - Runtime environment variables
process.env - - Project-level environment file
<project-root>/.env - - Claude configuration directory
.claude/.env - - Skills shared configuration
.claude/skills/.env - - Skill-specific configuration
.claude/skills/cloudflare*/.env
Required Environment Variables:
bash
CLOUDFLARE_API_TOKEN=your_api_token_here
CLOUDFLARE_ACCOUNT_ID=your_account_id_hereWhere to Get Credentials:
- API Token: Cloudflare Dashboard → My Profile → API Tokens → Create Token
- Account ID: Cloudflare Dashboard → Overview → Account ID (right sidebar)
Example .env File:
bash
undefinedCloudflare技能需要API凭证进行身份验证。系统按以下顺序查找API密钥:
- - 运行时环境变量
process.env - - 项目级环境文件
<project-root>/.env - - Claude配置目录
.claude/.env - - 技能共享配置
.claude/skills/.env - - 技能专属配置
.claude/skills/cloudflare*/.env
必填环境变量:
bash
CLOUDFLARE_API_TOKEN=your_api_token_here
CLOUDFLARE_ACCOUNT_ID=your_account_id_here获取凭证的位置:
- API Token:Cloudflare控制台 → 我的资料 → API令牌 → 创建令牌
- Account ID:Cloudflare控制台 → 概览 → 账户ID(右侧边栏)
示例.env文件:
bash
undefinedSee .claude/skills/.env.example for complete configuration
完整配置请参考.claude/skills/.env.example
CLOUDFLARE_API_TOKEN=abc123...
CLOUDFLARE_ACCOUNT_ID=def456...
undefinedCLOUDFLARE_API_TOKEN=abc123...
CLOUDFLARE_ACCOUNT_ID=def456...
undefinedGetting Started with Workers
Workers快速入门
Installation
安装
bash
undefinedbash
undefinedInstall Wrangler CLI
安装Wrangler CLI
npm install -g wrangler
npm install -g wrangler
Login to Cloudflare
登录Cloudflare
wrangler login
wrangler login
Create new project
创建新项目
wrangler init my-worker
cd my-worker
wrangler init my-worker
cd my-worker
Start local development
启动本地开发
wrangler dev
wrangler dev
Deploy to production
部署到生产环境
wrangler deploy
undefinedwrangler deploy
undefinedBasic Worker
基础Worker示例
typescript
// src/index.ts
export default {
async fetch(request: Request, env: Env): Promise<Response> {
return new Response('Hello from Cloudflare Workers!');
}
};typescript
// src/index.ts
export default {
async fetch(request: Request, env: Env): Promise<Response> {
return new Response('Hello from Cloudflare Workers!');
}
};Configuration (wrangler.toml)
配置文件(wrangler.toml)
toml
name = "my-worker"
main = "src/index.ts"
compatibility_date = "2024-01-01"toml
name = "my-worker"
main = "src/index.ts"
compatibility_date = "2024-01-01"Environment variables
环境变量
[vars]
ENVIRONMENT = "production"
[vars]
ENVIRONMENT = "production"
Bindings (added per product below)
绑定配置(各产品配置见下文)
undefinedundefinedLanguage Support
语言支持
- JavaScript/TypeScript: Primary language (full Node.js compatibility)
- Python: Beta support via Workers Python
- Rust: Compile to WebAssembly
- JavaScript/TypeScript:主要开发语言(完整兼容Node.js)
- Python:通过Workers Python提供Beta支持
- Rust:编译为WebAssembly运行
Storage Products
存储产品
D1 (SQLite Database)
D1(SQLite数据库)
Use Cases: Relational data, complex queries, ACID transactions
Setup:
bash
undefined适用场景:关系型数据、复杂查询、ACID事务
设置步骤:
bash
undefinedCreate database
创建数据库
wrangler d1 create my-database
wrangler d1 create my-database
Add to wrangler.toml
添加到wrangler.toml
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "YOUR_DATABASE_ID"
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "YOUR_DATABASE_ID"
Generate and apply schema
生成并应用Schema
wrangler d1 execute my-database --file=./schema.sql
**Usage**:
```typescript
export default {
async fetch(request: Request, env: Env) {
// Query
const result = await env.DB.prepare(
"SELECT * FROM users WHERE id = ?"
).bind(userId).first();
// Insert
await env.DB.prepare(
"INSERT INTO users (name, email) VALUES (?, ?)"
).bind("Alice", "alice@example.com").run();
// Batch (atomic)
await env.DB.batch([
env.DB.prepare("UPDATE accounts SET balance = balance - 100 WHERE id = ?").bind(user1),
env.DB.prepare("UPDATE accounts SET balance = balance + 100 WHERE id = ?").bind(user2)
]);
return new Response(JSON.stringify(result));
}
};Key Features:
- Global read replication (low-latency reads)
- Single-writer consistency
- Standard SQLite syntax
- 25GB database size limit
wrangler d1 execute my-database --file=./schema.sql
**使用示例**:
```typescript
export default {
async fetch(request: Request, env: Env) {
// 查询
const result = await env.DB.prepare(
"SELECT * FROM users WHERE id = ?"
).bind(userId).first();
// 插入
await env.DB.prepare(
"INSERT INTO users (name, email) VALUES (?, ?)"
).bind("Alice", "alice@example.com").run();
// 批量操作(原子性)
await env.DB.batch([
env.DB.prepare("UPDATE accounts SET balance = balance - 100 WHERE id = ?").bind(user1),
env.DB.prepare("UPDATE accounts SET balance = balance + 100 WHERE id = ?").bind(user2)
]);
return new Response(JSON.stringify(result));
}
};核心特性:
- 全局读取复制(低延迟读取)
- 单写入者一致性
- 标准SQLite语法
- 25GB数据库容量限制
KV (Key-Value Store)
KV(键值存储)
Use Cases: Cache, sessions, feature flags, rate limiting
Setup:
bash
undefined适用场景:缓存、会话、功能开关、速率限制
设置步骤:
bash
undefinedCreate namespace
创建命名空间
wrangler kv:namespace create MY_KV
wrangler kv:namespace create MY_KV
Add to wrangler.toml
添加到wrangler.toml
[[kv_namespaces]]
binding = "KV"
id = "YOUR_NAMESPACE_ID"
**Usage**:
```typescript
export default {
async fetch(request: Request, env: Env) {
// Put with TTL
await env.KV.put("session:token", JSON.stringify(data), {
expirationTtl: 3600 // 1 hour
});
// Get
const data = await env.KV.get("session:token", "json");
// Delete
await env.KV.delete("session:token");
// List with prefix
const list = await env.KV.list({ prefix: "user:123:" });
return new Response(JSON.stringify(data));
}
};Key Features:
- Sub-millisecond reads (edge-cached)
- Eventual consistency (~60 seconds globally)
- 25MB value size limit
- Automatic expiration (TTL)
[[kv_namespaces]]
binding = "KV"
id = "YOUR_NAMESPACE_ID"
**使用示例**:
```typescript
export default {
async fetch(request: Request, env: Env) {
// 存入带TTL的数据
await env.KV.put("session:token", JSON.stringify(data), {
expirationTtl: 3600 // 1小时
});
// 获取数据
const data = await env.KV.get("session:token", "json");
// 删除数据
await env.KV.delete("session:token");
// 按前缀列出数据
const list = await env.KV.list({ prefix: "user:123:" });
return new Response(JSON.stringify(data));
}
};核心特性:
- 亚毫秒级读取(边缘缓存)
- 最终一致性(全球同步约60秒)
- 25MB单值大小限制
- 自动过期(TTL)
R2 (Object Storage)
R2(对象存储)
Use Cases: File storage, media hosting, backups, static assets
Setup:
bash
undefined适用场景:文件存储、媒体托管、备份、静态资源
设置步骤:
bash
undefinedCreate bucket
创建存储桶
wrangler r2 bucket create my-bucket
wrangler r2 bucket create my-bucket
Add to wrangler.toml
添加到wrangler.toml
[[r2_buckets]]
binding = "R2_BUCKET"
bucket_name = "my-bucket"
**Usage**:
```typescript
export default {
async fetch(request: Request, env: Env) {
// Put object
await env.R2_BUCKET.put("path/to/file.jpg", fileBuffer, {
httpMetadata: {
contentType: "image/jpeg"
}
});
// Get object
const object = await env.R2_BUCKET.get("path/to/file.jpg");
if (!object) {
return new Response("Not found", { status: 404 });
}
// Stream response
return new Response(object.body, {
headers: {
"Content-Type": object.httpMetadata?.contentType || "application/octet-stream"
}
});
// Delete
await env.R2_BUCKET.delete("path/to/file.jpg");
// List
const list = await env.R2_BUCKET.list({ prefix: "uploads/" });
}
};Key Features:
- S3-compatible API
- Zero egress fees (huge cost advantage)
- Unlimited storage
- 5TB object size limit
- Multipart upload support
[[r2_buckets]]
binding = "R2_BUCKET"
bucket_name = "my-bucket"
**使用示例**:
```typescript
export default {
async fetch(request: Request, env: Env) {
// 上传对象
await env.R2_BUCKET.put("path/to/file.jpg", fileBuffer, {
httpMetadata: {
contentType: "image/jpeg"
}
});
// 获取对象
const object = await env.R2_BUCKET.get("path/to/file.jpg");
if (!object) {
return new Response("Not found", { status: 404 });
}
// 流式响应
return new Response(object.body, {
headers: {
"Content-Type": object.httpMetadata?.contentType || "application/octet-stream"
}
});
// 删除对象
await env.R2_BUCKET.delete("path/to/file.jpg");
// 列出对象
const list = await env.R2_BUCKET.list({ prefix: "uploads/" });
}
};核心特性:
- S3兼容API
- 零出口费用(巨大成本优势)
- 无限存储容量
- 5TB单对象大小限制
- 分片上传支持
Durable Objects
Durable Objects
Use Cases: Real-time apps, WebSockets, coordination, stateful logic
Setup:
toml
undefined适用场景:实时应用、WebSocket、协调逻辑、有状态业务
设置步骤:
toml
undefinedwrangler.toml
wrangler.toml
[[durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"
script_name = "my-worker"
**Usage**:
```typescript
// Define Durable Object class
export class Counter {
state: DurableObjectState;
constructor(state: DurableObjectState, env: Env) {
this.state = state;
}
async fetch(request: Request) {
// Get current count
let count = (await this.state.storage.get<number>('count')) || 0;
// Increment
count++;
await this.state.storage.put('count', count);
return new Response(JSON.stringify({ count }));
}
}
// Use in Worker
export default {
async fetch(request: Request, env: Env) {
// Get Durable Object instance
const id = env.COUNTER.idFromName("global-counter");
const counter = env.COUNTER.get(id);
// Forward request
return counter.fetch(request);
}
};WebSocket Example:
typescript
export class ChatRoom {
state: DurableObjectState;
sessions: Set<WebSocket>;
constructor(state: DurableObjectState) {
this.state = state;
this.sessions = new Set();
}
async fetch(request: Request) {
const pair = new WebSocketPair();
const [client, server] = Object.values(pair);
this.state.acceptWebSocket(server);
this.sessions.add(server);
return new Response(null, { status: 101, webSocket: client });
}
async webSocketMessage(ws: WebSocket, message: string) {
// Broadcast to all connected clients
for (const session of this.sessions) {
session.send(message);
}
}
async webSocketClose(ws: WebSocket) {
this.sessions.delete(ws);
}
}Key Features:
- Single-instance coordination (strong consistency)
- Persistent storage (1GB limit on paid plans)
- WebSocket support
- Automatic hibernation for inactive objects
[[durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"
script_name = "my-worker"
**使用示例**:
```typescript
// 定义Durable Object类
export class Counter {
state: DurableObjectState;
constructor(state: DurableObjectState, env: Env) {
this.state = state;
}
async fetch(request: Request) {
// 获取当前计数
let count = (await this.state.storage.get<number>('count')) || 0;
// 递增计数
count++;
await this.state.storage.put('count', count);
return new Response(JSON.stringify({ count }));
}
}
// 在Worker中使用
export default {
async fetch(request: Request, env: Env) {
// 获取Durable Object实例
const id = env.COUNTER.idFromName("global-counter");
const counter = env.COUNTER.get(id);
// 转发请求
return counter.fetch(request);
}
};WebSocket示例:
typescript
export class ChatRoom {
state: DurableObjectState;
sessions: Set<WebSocket>;
constructor(state: DurableObjectState) {
this.state = state;
this.sessions = new Set();
}
async fetch(request: Request) {
const pair = new WebSocketPair();
const [client, server] = Object.values(pair);
this.state.acceptWebSocket(server);
this.sessions.add(server);
return new Response(null, { status: 101, webSocket: client });
}
async webSocketMessage(ws: WebSocket, message: string) {
// 广播消息到所有连接客户端
for (const session of this.sessions) {
session.send(message);
}
}
async webSocketClose(ws: WebSocket) {
this.sessions.delete(ws);
}
}核心特性:
- 单实例协调(强一致性)
- 持久化存储(付费计划1GB限制)
- WebSocket支持
- 非活动对象自动休眠
Queues
Queues
Use Cases: Background jobs, email sending, async processing
Setup:
toml
undefined适用场景:后台任务、邮件发送、异步处理
设置步骤:
toml
undefinedwrangler.toml
wrangler.toml
[[queues.producers]]
binding = "MY_QUEUE"
queue = "my-queue"
[[queues.consumers]]
queue = "my-queue"
max_batch_size = 10
max_batch_timeout = 30
**Usage**:
```typescript
// Producer: Send messages
export default {
async fetch(request: Request, env: Env) {
await env.MY_QUEUE.send({
type: 'email',
to: 'user@example.com',
subject: 'Welcome!'
});
return new Response('Message queued');
}
};
// Consumer: Process messages
export default {
async queue(batch: MessageBatch<any>, env: Env) {
for (const message of batch.messages) {
try {
await processMessage(message.body);
message.ack(); // Acknowledge success
} catch (error) {
message.retry(); // Retry on failure
}
}
}
};Key Features:
- At-least-once delivery
- Automatic retries (exponential backoff)
- Dead-letter queue support
- Batch processing
[[queues.producers]]
binding = "MY_QUEUE"
queue = "my-queue"
[[queues.consumers]]
queue = "my-queue"
max_batch_size = 10
max_batch_timeout = 30
**使用示例**:
```typescript
// 生产者:发送消息
export default {
async fetch(request: Request, env: Env) {
await env.MY_QUEUE.send({
type: 'email',
to: 'user@example.com',
subject: 'Welcome!'
});
return new Response('Message queued');
}
};
// 消费者:处理消息
export default {
async queue(batch: MessageBatch<any>, env: Env) {
for (const message of batch.messages) {
try {
await processMessage(message.body);
message.ack(); // 确认处理成功
} catch (error) {
message.retry(); // 失败时重试
}
}
}
};核心特性:
- 至少一次交付
- 自动重试(指数退避)
- 死信队列支持
- 批量处理
AI Products
AI产品
Workers AI
Workers AI
Use Cases: Run AI models directly on the edge
Setup:
toml
undefined适用场景:在边缘直接运行AI模型
设置步骤:
toml
undefinedwrangler.toml
wrangler.toml
[ai]
binding = "AI"
**Usage**:
```typescript
export default {
async fetch(request: Request, env: Env) {
// Text generation
const response = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
messages: [
{ role: 'user', content: 'What is edge computing?' }
]
});
// Image classification
const imageResponse = await env.AI.run('@cf/microsoft/resnet-50', {
image: imageBuffer
});
// Text embeddings
const embeddings = await env.AI.run('@cf/baai/bge-base-en-v1.5', {
text: 'Hello world'
});
return new Response(JSON.stringify(response));
}
};Available Models:
- LLMs: Llama 3, Mistral, Gemma, Qwen
- Image: Stable Diffusion, DALL-E, ResNet
- Embeddings: BGE, GTE
- Translation, summarization, sentiment analysis
[ai]
binding = "AI"
**使用示例**:
```typescript
export default {
async fetch(request: Request, env: Env) {
// 文本生成
const response = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
messages: [
{ role: 'user', content: 'What is edge computing?' }
]
});
// 图像分类
const imageResponse = await env.AI.run('@cf/microsoft/resnet-50', {
image: imageBuffer
});
// 文本嵌入
const embeddings = await env.AI.run('@cf/baai/bge-base-en-v1.5', {
text: 'Hello world'
});
return new Response(JSON.stringify(response));
}
};可用模型:
- 大语言模型:Llama 3、Mistral、Gemma、Qwen
- 图像模型:Stable Diffusion、DALL-E、ResNet
- 嵌入模型:BGE、GTE
- 翻译、摘要、情感分析
AI Gateway
AI Gateway
Use Cases: Unified interface for AI providers with caching, rate limiting, analytics
Setup:
typescript
// OpenAI via AI Gateway
const response = await fetch(
'https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/openai/chat/completions',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${env.OPENAI_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'gpt-4',
messages: [{ role: 'user', content: 'Hello!' }]
})
}
);Features:
- Request caching (reduce costs)
- Rate limiting
- Analytics and logging
- Supports OpenAI, Anthropic, HuggingFace, etc.
适用场景:统一AI提供商接口,具备缓存、速率限制、分析功能
设置步骤:
typescript
// 通过AI Gateway调用OpenAI
const response = await fetch(
'https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/openai/chat/completions',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${env.OPENAI_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'gpt-4',
messages: [{ role: 'user', content: 'Hello!' }]
})
}
);核心特性:
- 请求缓存(降低成本)
- 速率限制
- 分析与日志
- 支持OpenAI、Anthropic、HuggingFace等
Agents
Agents
Use Cases: Build AI agents with tools and workflows
typescript
import { Agent } from '@cloudflare/agents';
export default {
async fetch(request: Request, env: Env) {
const agent = new Agent({
model: '@cf/meta/llama-3-8b-instruct',
tools: [
{
name: 'get_weather',
description: 'Get current weather',
parameters: {
type: 'object',
properties: {
location: { type: 'string' }
}
},
handler: async ({ location }) => {
// Fetch weather data
return { temperature: 72, conditions: 'sunny' };
}
}
]
});
const result = await agent.run('What is the weather in San Francisco?');
return new Response(JSON.stringify(result));
}
};适用场景:构建带工具与工作流的AI代理
typescript
import { Agent } from '@cloudflare/agents';
export default {
async fetch(request: Request, env: Env) {
const agent = new Agent({
model: '@cf/meta/llama-3-8b-instruct',
tools: [
{
name: 'get_weather',
description: 'Get current weather',
parameters: {
type: 'object',
properties: {
location: { type: 'string' }
}
},
handler: async ({ location }) => {
// 获取天气数据
return { temperature: 72, conditions: 'sunny' };
}
}
]
});
const result = await agent.run('What is the weather in San Francisco?');
return new Response(JSON.stringify(result));
}
};AI Search (RAG)
AI搜索(RAG)
Use Cases: Build retrieval-augmented generation applications
typescript
import { VectorizeIndex } from '@cloudflare/workers-types';
export default {
async fetch(request: Request, env: Env) {
// Generate embeddings
const embeddings = await env.AI.run('@cf/baai/bge-base-en-v1.5', {
text: query
});
// Search vector database
const results = await env.VECTORIZE_INDEX.query(embeddings.data[0], {
topK: 5
});
// Generate response with context
const response = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
messages: [
{
role: 'system',
content: `Context: ${results.matches.map(m => m.metadata.text).join('\n')}`
},
{ role: 'user', content: query }
]
});
return new Response(JSON.stringify(response));
}
};适用场景:构建检索增强生成应用
typescript
import { VectorizeIndex } from '@cloudflare/workers-types';
export default {
async fetch(request: Request, env: Env) {
// 生成嵌入向量
const embeddings = await env.AI.run('@cf/baai/bge-base-en-v1.5', {
text: query
});
// 搜索向量数据库
const results = await env.VECTORIZE_INDEX.query(embeddings.data[0], {
topK: 5
});
// 结合上下文生成响应
const response = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
messages: [
{
role: 'system',
content: `Context: ${results.matches.map(m => m.metadata.text).join('\n')}`
},
{ role: 'user', content: query }
]
});
return new Response(JSON.stringify(response));
}
};Cloudflare Pages
Cloudflare Pages
Static Sites + Serverless Functions
静态站点 + 无服务器函数
Deployment:
bash
undefined部署方式:
bash
undefinedDeploy via Git (recommended)
通过Git部署(推荐)
Connect GitHub repo in Cloudflare dashboard
在Cloudflare控制台连接GitHub仓库
Or deploy via CLI
或通过CLI部署
wrangler pages deploy ./dist
undefinedwrangler pages deploy ./dist
undefinedPages Functions
Pages Functions
Directory-based routing in :
functions/functions/
├── api/
│ ├── users/
│ │ └── [id].ts # /api/users/:id
│ └── posts.ts # /api/posts
└── _middleware.ts # Global middlewareExample Function:
typescript
// functions/api/users/[id].ts
export async function onRequestGet(context) {
const { params, env } = context;
const user = await env.DB.prepare(
"SELECT * FROM users WHERE id = ?"
).bind(params.id).first();
return new Response(JSON.stringify(user), {
headers: { 'Content-Type': 'application/json' }
});
}Middleware:
typescript
// functions/_middleware.ts
export async function onRequest(context) {
const start = Date.now();
const response = await context.next();
const duration = Date.now() - start;
console.log(`${context.request.method} ${context.request.url} - ${duration}ms`);
return response;
}基于目录的路由:
functions/functions/
├── api/
│ ├── users/
│ │ └── [id].ts # /api/users/:id
│ └── posts.ts # /api/posts
└── _middleware.ts # 全局中间件示例函数:
typescript
// functions/api/users/[id].ts
export async function onRequestGet(context) {
const { params, env } = context;
const user = await env.DB.prepare(
"SELECT * FROM users WHERE id = ?"
).bind(params.id).first();
return new Response(JSON.stringify(user), {
headers: { 'Content-Type': 'application/json' }
});
}中间件示例:
typescript
// functions/_middleware.ts
export async function onRequest(context) {
const start = Date.now();
const response = await context.next();
const duration = Date.now() - start;
console.log(`${context.request.method} ${context.request.url} - ${duration}ms`);
return response;
}Framework Support
框架支持
Next.js:
bash
npx create-next-app@latest my-app
cd my-app
npm install -D @cloudflare/next-on-pages
npx @cloudflare/next-on-pages
wrangler pages deploy .vercel/output/staticRemix:
bash
npx create-remix@latest --template cloudflare/remixAstro:
bash
npm create astro@latestNext.js:
bash
npx create-next-app@latest my-app
cd my-app
npm install -D @cloudflare/next-on-pages
npx @cloudflare/next-on-pages
wrangler pages deploy .vercel/output/staticRemix:
bash
npx create-remix@latest --template cloudflare/remixAstro:
bash
npm create astro@latestSelect "Cloudflare" adapter during setup
安装过程中选择"Cloudflare"适配器
**SvelteKit**:
```bash
npm create svelte@latest
npm install -D @sveltejs/adapter-cloudflare
**SvelteKit**:
```bash
npm create svelte@latest
npm install -D @sveltejs/adapter-cloudflareWrangler CLI Essentials
Wrangler CLI核心命令
Core Commands
基础命令
bash
undefinedbash
undefinedDevelopment
开发
wrangler dev # Local development server
wrangler dev --remote # Dev on real Cloudflare infrastructure
wrangler dev # 本地开发服务器
wrangler dev --remote # 在真实Cloudflare基础设施上开发
Deployment
部署
wrangler deploy # Deploy to production
wrangler deploy --dry-run # Preview changes without deploying
wrangler deploy # 部署到生产环境
wrangler deploy --dry-run # 预览变更不实际部署
Logs
日志
wrangler tail # Real-time logs
wrangler tail --format pretty # Formatted logs
wrangler tail # 实时日志
wrangler tail --format pretty # 格式化日志
Versions
版本管理
wrangler deployments list # List deployments
wrangler rollback [version] # Rollback to previous version
wrangler deployments list # 列出部署版本
wrangler rollback [version] # 回滚到之前版本
Secrets
密钥管理
wrangler secret put SECRET_NAME # Add secret
wrangler secret list # List secrets
wrangler secret delete SECRET_NAME # Delete secret
undefinedwrangler secret put SECRET_NAME # 添加密钥
wrangler secret list # 列出密钥
wrangler secret delete SECRET_NAME # 删除密钥
undefinedProject Management
项目管理
bash
undefinedbash
undefinedCreate projects
创建项目
wrangler init my-worker # Create Worker
wrangler pages project create # Create Pages project
wrangler init my-worker # 创建Worker
wrangler pages project create # 创建Pages项目
Database
数据库操作
wrangler d1 create my-db # Create D1 database
wrangler d1 execute my-db --file=schema.sql
wrangler d1 execute my-db --command="SELECT * FROM users"
wrangler d1 create my-db # 创建D1数据库
wrangler d1 execute my-db --file=schema.sql
wrangler d1 execute my-db --command="SELECT * FROM users"
KV
KV操作
wrangler kv:namespace create MY_KV
wrangler kv:key put --binding=MY_KV "key" "value"
wrangler kv:key get --binding=MY_KV "key"
wrangler kv:namespace create MY_KV
wrangler kv:key put --binding=MY_KV "key" "value"
wrangler kv:key get --binding=MY_KV "key"
R2
R2操作
wrangler r2 bucket create my-bucket
wrangler r2 object put my-bucket/file.txt --file=./file.txt
undefinedwrangler r2 bucket create my-bucket
wrangler r2 object put my-bucket/file.txt --file=./file.txt
undefinedIntegration Patterns
集成模式
Full-Stack Application Architecture
全栈应用架构
┌─────────────────────────────────────────┐
│ Cloudflare Pages (Frontend) │
│ Next.js / Remix / Astro / SvelteKit │
└──────────────────┬──────────────────────┘
│
┌──────────────────▼──────────────────────┐
│ Workers (API Layer / BFF) │
│ - Routing │
│ - Authentication │
│ - Business logic │
└─┬──────┬──────┬──────┬──────┬───────────┘
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────────────┐
│ D1 │ │ KV │ │ R2 │ │ DO │ │ Workers AI │
└────┘ └────┘ └────┘ └────┘ └────────────┘┌─────────────────────────────────────────┐
│ Cloudflare Pages (前端) │
│ Next.js / Remix / Astro / SvelteKit │
└──────────────────┬──────────────────────┘
│
┌──────────────────▼──────────────────────┐
│ Workers (API层 / BFF) │
│ - 路由 │
│ - 身份验证 │
│ - 业务逻辑 │
└─┬──────┬──────┬──────┬──────┬───────────┘
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────────────┐
│ D1 │ │ KV │ │ R2 │ │ DO │ │ Workers AI │
└────┘ └────┘ └────┘ └────┘ └────────────┘Polyglot Storage Pattern
多语言存储模式
typescript
export default {
async fetch(request: Request, env: Env) {
const url = new URL(request.url);
// KV: Fast cache
const cached = await env.KV.get(url.pathname);
if (cached) return new Response(cached);
// D1: Structured data
const user = await env.DB.prepare(
"SELECT * FROM users WHERE id = ?"
).bind(userId).first();
// R2: Media files
const avatar = await env.R2_BUCKET.get(`avatars/${user.id}.jpg`);
// Durable Objects: Real-time coordination
const chat = env.CHAT_ROOM.get(env.CHAT_ROOM.idFromName(roomId));
// Queue: Async processing
await env.EMAIL_QUEUE.send({ to: user.email, template: 'welcome' });
return new Response(JSON.stringify({ user, avatar }));
}
};typescript
export default {
async fetch(request: Request, env: Env) {
const url = new URL(request.url);
// KV: 快速缓存
const cached = await env.KV.get(url.pathname);
if (cached) return new Response(cached);
// D1: 结构化数据
const user = await env.DB.prepare(
"SELECT * FROM users WHERE id = ?"
).bind(userId).first();
// R2: 媒体文件
const avatar = await env.R2_BUCKET.get(`avatars/${user.id}.jpg`);
// Durable Objects: 实时协调
const chat = env.CHAT_ROOM.get(env.CHAT_ROOM.idFromName(roomId));
// Queue: 异步处理
await env.EMAIL_QUEUE.send({ to: user.email, template: 'welcome' });
return new Response(JSON.stringify({ user, avatar }));
}
};Authentication Pattern
身份验证模式
typescript
import { verifyJWT, createJWT } from './jwt';
export default {
async fetch(request: Request, env: Env) {
const url = new URL(request.url);
// Login
if (url.pathname === '/api/login') {
const { email, password } = await request.json();
const user = await env.DB.prepare(
"SELECT * FROM users WHERE email = ?"
).bind(email).first();
if (!user || !await verifyPassword(password, user.password_hash)) {
return new Response('Invalid credentials', { status: 401 });
}
const token = await createJWT({ userId: user.id }, env.JWT_SECRET);
return new Response(JSON.stringify({ token }), {
headers: { 'Content-Type': 'application/json' }
});
}
// Protected route
const authHeader = request.headers.get('Authorization');
if (!authHeader) {
return new Response('Unauthorized', { status: 401 });
}
const token = authHeader.replace('Bearer ', '');
const payload = await verifyJWT(token, env.JWT_SECRET);
// Store session in KV
await env.KV.put(`session:${payload.userId}`, JSON.stringify(payload), {
expirationTtl: 86400 // 24 hours
});
return new Response('Authenticated');
}
};typescript
import { verifyJWT, createJWT } from './jwt';
export default {
async fetch(request: Request, env: Env) {
const url = new URL(request.url);
// 登录接口
if (url.pathname === '/api/login') {
const { email, password } = await request.json();
const user = await env.DB.prepare(
"SELECT * FROM users WHERE email = ?"
).bind(email).first();
if (!user || !await verifyPassword(password, user.password_hash)) {
return new Response('Invalid credentials', { status: 401 });
}
const token = await createJWT({ userId: user.id }, env.JWT_SECRET);
return new Response(JSON.stringify({ token }), {
headers: { 'Content-Type': 'application/json' }
});
}
// 受保护路由
const authHeader = request.headers.get('Authorization');
if (!authHeader) {
return new Response('Unauthorized', { status: 401 });
}
const token = authHeader.replace('Bearer ', '');
const payload = await verifyJWT(token, env.JWT_SECRET);
// 将会话存储到KV
await env.KV.put(`session:${payload.userId}`, JSON.stringify(payload), {
expirationTtl: 86400 // 24小时
});
return new Response('Authenticated');
}
};Cache Strategy
缓存策略
typescript
export default {
async fetch(request: Request, env: Env) {
const cache = caches.default;
const cacheKey = new Request(request.url);
// Check cache
let response = await cache.match(cacheKey);
if (response) return response;
// Check KV (distributed cache)
const kvCached = await env.KV.get(request.url);
if (kvCached) {
response = new Response(kvCached);
await cache.put(cacheKey, response.clone());
return response;
}
// Fetch from origin (D1, R2, etc.)
const data = await fetchFromOrigin(request, env);
response = new Response(data);
// Store in both caches
await cache.put(cacheKey, response.clone());
await env.KV.put(request.url, data, { expirationTtl: 3600 });
return response;
}
};typescript
export default {
async fetch(request: Request, env: Env) {
const cache = caches.default;
const cacheKey = new Request(request.url);
// 检查本地缓存
let response = await cache.match(cacheKey);
if (response) return response;
// 检查KV(分布式缓存)
const kvCached = await env.KV.get(request.url);
if (kvCached) {
response = new Response(kvCached);
await cache.put(cacheKey, response.clone());
return response;
}
// 从源获取数据(D1、R2等)
const data = await fetchFromOrigin(request, env);
response = new Response(data);
// 存储到两种缓存
await cache.put(cacheKey, response.clone());
await env.KV.put(request.url, data, { expirationTtl: 3600 });
return response;
}
};Best Practices
最佳实践
Performance
性能优化
- Minimize Cold Starts: Keep Workers lightweight (<1MB bundled)
- Use Bindings Over Fetch: Direct bindings are faster than HTTP calls
- Edge Caching: Leverage KV and Cache API for frequently accessed data
- Batch Operations: Use D1 batch for multiple queries
- Stream Large Responses: Use streams for large files
Response.body
- 最小化冷启动:保持Worker轻量化(打包后<1MB)
- 使用绑定而非Fetch:直接绑定比HTTP调用更快
- 边缘缓存:利用KV和Cache API缓存频繁访问的数据
- 批量操作:使用D1 batch处理多个查询
- 流式大响应:对大文件使用流
Response.body
Security
安全实践
- Secrets Management: Use for API keys
wrangler secret - Environment Isolation: Separate production/staging/development
- Input Validation: Sanitize user input
- Rate Limiting: Use KV or Durable Objects for rate limiting
- CORS: Configure proper CORS headers
- 密钥管理:使用存储API密钥
wrangler secret - 环境隔离:分离生产/预发布/开发环境
- 输入验证:对用户输入进行 sanitize 处理
- 速率限制:使用KV或Durable Objects实现速率限制
- CORS配置:设置正确的CORS头
Cost Optimization
成本优化
- R2 for Large Files: Zero egress fees vs S3
- KV for Caching: Reduce D1/R2 requests
- Request Deduplication: Cache identical requests
- Efficient Queries: Index D1 tables properly
- Monitor Usage: Use Cloudflare Analytics
- R2存储大文件:零出口费用,优于S3
- KV缓存:减少D1/R2请求
- 请求去重:缓存相同请求
- 高效查询:为D1表合理建立索引
- 监控使用:使用Cloudflare分析工具
Development Workflow
开发工作流
- Local Development: Use for testing
wrangler dev - Type Safety: Use TypeScript with
@cloudflare/workers-types - Testing: Use Vitest with
unstable_dev() - CI/CD: GitHub Actions with
cloudflare/wrangler-action - Gradual Deployments: Use percentage-based rollouts
- 本地开发:使用进行测试
wrangler dev - 类型安全:使用TypeScript配合
@cloudflare/workers-types - 测试:使用Vitest和
unstable_dev() - CI/CD:GitHub Actions配合
cloudflare/wrangler-action - 灰度发布:使用百分比式逐步部署
Common Patterns
常见模式
API Gateway
API网关
typescript
import { Hono } from 'hono';
const app = new Hono();
app.get('/api/users/:id', async (c) => {
const user = await c.env.DB.prepare(
"SELECT * FROM users WHERE id = ?"
).bind(c.req.param('id')).first();
return c.json(user);
});
app.post('/api/users', async (c) => {
const { name, email } = await c.req.json();
await c.env.DB.prepare(
"INSERT INTO users (name, email) VALUES (?, ?)"
).bind(name, email).run();
return c.json({ success: true }, 201);
});
export default app;typescript
import { Hono } from 'hono';
const app = new Hono();
app.get('/api/users/:id', async (c) => {
const user = await c.env.DB.prepare(
"SELECT * FROM users WHERE id = ?"
).bind(c.req.param('id')).first();
return c.json(user);
});
app.post('/api/users', async (c) => {
const { name, email } = await c.req.json();
await c.env.DB.prepare(
"INSERT INTO users (name, email) VALUES (?, ?)"
).bind(name, email).run();
return c.json({ success: true }, 201);
});
export default app;Image Transformation
图片转换
typescript
export default {
async fetch(request: Request, env: Env) {
const url = new URL(request.url);
const imageKey = url.pathname.replace('/images/', '');
// Get from R2
const object = await env.R2_BUCKET.get(imageKey);
if (!object) {
return new Response('Not found', { status: 404 });
}
// Transform with Cloudflare Images
return new Response(object.body, {
headers: {
'Content-Type': object.httpMetadata?.contentType || 'image/jpeg',
'Cache-Control': 'public, max-age=86400',
'cf-image-resize': JSON.stringify({
width: 800,
height: 600,
fit: 'cover'
})
}
});
}
};typescript
export default {
async fetch(request: Request, env: Env) {
const url = new URL(request.url);
const imageKey = url.pathname.replace('/images/', '');
// 从R2获取图片
const object = await env.R2_BUCKET.get(imageKey);
if (!object) {
return new Response('Not found', { status: 404 });
}
// 使用Cloudflare Images转换
return new Response(object.body, {
headers: {
'Content-Type': object.httpMetadata?.contentType || 'image/jpeg',
'Cache-Control': 'public, max-age=86400',
'cf-image-resize': JSON.stringify({
width: 800,
height: 600,
fit: 'cover'
})
}
});
}
};Rate Limiting (KV)
速率限制(基于KV)
typescript
async function rateLimit(ip: string, env: Env): Promise<boolean> {
const key = `ratelimit:${ip}`;
const limit = 100; // requests per minute
const window = 60; // seconds
const current = await env.KV.get(key);
const count = current ? parseInt(current) : 0;
if (count >= limit) {
return false; // Rate limit exceeded
}
await env.KV.put(key, (count + 1).toString(), {
expirationTtl: window
});
return true;
}
export default {
async fetch(request: Request, env: Env) {
const ip = request.headers.get('CF-Connecting-IP') || 'unknown';
if (!await rateLimit(ip, env)) {
return new Response('Rate limit exceeded', { status: 429 });
}
return new Response('OK');
}
};typescript
async function rateLimit(ip: string, env: Env): Promise<boolean> {
const key = `ratelimit:${ip}`;
const limit = 100; // 每分钟请求数
const window = 60; // 秒
const current = await env.KV.get(key);
const count = current ? parseInt(current) : 0;
if (count >= limit) {
return false; // 超过速率限制
}
await env.KV.put(key, (count + 1).toString(), {
expirationTtl: window
});
return true;
}
export default {
async fetch(request: Request, env: Env) {
const ip = request.headers.get('CF-Connecting-IP') || 'unknown';
if (!await rateLimit(ip, env)) {
return new Response('Rate limit exceeded', { status: 429 });
}
return new Response('OK');
}
};Scheduled Jobs
定时任务
toml
undefinedtoml
undefinedwrangler.toml
wrangler.toml
[triggers]
crons = ["0 0 * * *"] # Daily at midnight
```typescript
export default {
async scheduled(event: ScheduledEvent, env: Env) {
// Cleanup old sessions
const sessions = await env.KV.list({ prefix: 'session:' });
for (const key of sessions.keys) {
const session = await env.KV.get(key.name, 'json');
if (session.expiresAt < Date.now()) {
await env.KV.delete(key.name);
}
}
}
};[triggers]
crons = ["0 0 * * *"] # 每天午夜执行
```typescript
export default {
async scheduled(event: ScheduledEvent, env: Env) {
// 清理旧会话
const sessions = await env.KV.list({ prefix: 'session:' });
for (const key of sessions.keys) {
const session = await env.KV.get(key.name, 'json');
if (session.expiresAt < Date.now()) {
await env.KV.delete(key.name);
}
}
}
};Troubleshooting
故障排除
Common Issues
常见问题
"Module not found" errors
- Ensure dependencies are in
package.json - Run before deploying
npm install - Check compatibility_date in wrangler.toml
Database connection errors (D1)
- Verify database_id in wrangler.toml
- Check database exists:
wrangler d1 list - Run migrations:
wrangler d1 execute DB --file=schema.sql
KV not found errors
- Create namespace:
wrangler kv:namespace create MY_KV - Add binding to wrangler.toml
- Deploy after configuration changes
Cold start timeout
- Reduce bundle size (<1MB ideal)
- Remove unnecessary dependencies
- Use dynamic imports for large libraries
CORS errors
- Add CORS headers to responses:
typescript
return new Response(data, { headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type' } });
Deployment fails
- Check wrangler version:
wrangler --version - Verify authentication:
wrangler whoami - Review build errors in console output
"Module not found"错误
- 确保依赖已在中
package.json - 部署前运行
npm install - 检查wrangler.toml中的compatibility_date
数据库连接错误(D1)
- 验证wrangler.toml中的database_id
- 检查数据库是否存在:
wrangler d1 list - 运行迁移:
wrangler d1 execute DB --file=schema.sql
KV未找到错误
- 创建命名空间:
wrangler kv:namespace create MY_KV - 在wrangler.toml中添加绑定
- 配置变更后重新部署
冷启动超时
- 减小包大小(理想<1MB)
- 移除不必要的依赖
- 对大型库使用动态导入
CORS错误
- 为响应添加CORS头:
typescript
return new Response(data, { headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type' } });
部署失败
- 检查wrangler版本:
wrangler --version - 验证身份:
wrangler whoami - 查看控制台输出中的构建错误
Debugging
调试方法
bash
undefinedbash
undefinedReal-time logs
实时日志
wrangler tail
wrangler tail
Local debugging with breakpoints
本地断点调试
wrangler dev --local
wrangler dev --local
Remote debugging
远程调试
wrangler dev --remote
wrangler dev --remote
Check deployment status
检查部署状态
wrangler deployments list
undefinedwrangler deployments list
undefinedDecision Matrix
决策矩阵
| Need | Choose |
|---|---|
| Sub-millisecond reads | KV |
| SQL queries | D1 |
| Large files (>25MB) | R2 |
| Real-time WebSockets | Durable Objects |
| Async background jobs | Queues |
| ACID transactions | D1 |
| Strong consistency | Durable Objects |
| Zero egress costs | R2 |
| AI inference | Workers AI |
| Static site hosting | Pages |
| Serverless functions | Workers |
| Multi-provider AI | AI Gateway |
| 需求 | 选择方案 |
|---|---|
| 亚毫秒级读取 | KV |
| SQL查询 | D1 |
| 大文件(>25MB) | R2 |
| 实时WebSocket | Durable Objects |
| 异步后台任务 | Queues |
| ACID事务 | D1 |
| 强一致性 | Durable Objects |
| 零出口成本 | R2 |
| AI推理 | Workers AI |
| 静态站点托管 | Pages |
| 无服务器函数 | Workers |
| 多提供商AI | AI Gateway |
Framework-Specific Guides
框架专属指南
Next.js
Next.js
- Use adapter
@cloudflare/next-on-pages - Configure for edge runtime
next.config.js - Deploy via
wrangler pages deploy
- 使用适配器
@cloudflare/next-on-pages - 在中配置边缘运行时
next.config.js - 通过部署
wrangler pages deploy
Remix
Remix
- Use official Cloudflare template
- Configure for Workers
server.ts - Access bindings via
context.cloudflare.env
- 使用官方Cloudflare模板
- 在中配置Workers
server.ts - 通过访问绑定
context.cloudflare.env
Astro
Astro
- Use adapter
@astrojs/cloudflare - Enable SSR in
astro.config.mjs - Access env via
Astro.locals.runtime.env
- 使用适配器
@astrojs/cloudflare - 在中启用SSR
astro.config.mjs - 通过访问环境变量
Astro.locals.runtime.env
SvelteKit
SvelteKit
- Use
@sveltejs/adapter-cloudflare - Configure in
svelte.config.js - Access platform via
event.platform.env
- 使用
@sveltejs/adapter-cloudflare - 在中配置
svelte.config.js - 通过访问平台资源
event.platform.env
Resources
资源链接
- Documentation: https://developers.cloudflare.com
- Wrangler CLI: https://developers.cloudflare.com/workers/wrangler/
- Discord Community: https://discord.cloudflare.com
- Examples: https://developers.cloudflare.com/workers/examples/
- GitHub: https://github.com/cloudflare
- Status Page: https://www.cloudflarestatus.com
Implementation Checklist
实施检查清单
Workers Setup
Workers设置
- Install Wrangler CLI ()
npm install -g wrangler - Login to Cloudflare ()
wrangler login - Create project ()
wrangler init - Configure wrangler.toml
- Add environment variables/secrets
- Test locally ()
wrangler dev - Deploy ()
wrangler deploy
- 安装Wrangler CLI ()
npm install -g wrangler - 登录Cloudflare ()
wrangler login - 创建项目 ()
wrangler init - 配置wrangler.toml
- 添加环境变量/密钥
- 本地测试 ()
wrangler dev - 部署到生产环境 ()
wrangler deploy
Storage Setup (as needed)
存储服务设置(按需)
- Create D1 database and apply schema
- Create KV namespace
- Create R2 bucket
- Configure Durable Objects
- Set up Queues
- Add bindings to wrangler.toml
- 创建D1数据库并应用Schema
- 创建KV命名空间
- 创建R2存储桶
- 配置Durable Objects
- 设置Queues
- 在wrangler.toml中添加绑定
Pages Setup
Pages设置
- Connect Git repository or use CLI
- Configure build settings
- Set environment variables
- Add Pages Functions (if needed)
- Deploy and test
- 连接Git仓库或使用CLI部署
- 配置构建设置
- 设置环境变量
- 添加Pages Functions(如需)
- 部署并测试
Production Checklist
生产环境检查清单
- Set up custom domain
- Configure DNS records
- Enable SSL/TLS
- Set up monitoring/analytics
- Configure rate limiting
- Implement error handling
- Set up CI/CD pipeline
- Test gradual deployments
- Document rollback procedure
- Configure logging/observability
- 配置自定义域名
- 设置DNS记录
- 启用SSL/TLS
- 设置监控/分析
- 配置速率限制
- 实现错误处理
- 搭建CI/CD流水线
- 测试灰度发布
- 记录回滚流程
- 配置日志/可观测性