cloudflare
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCloudflare Platform
Cloudflare 平台
Build globally distributed applications on Cloudflare's edge network.
在Cloudflare边缘网络上构建全球分布式应用。
Quick Start
快速开始
bash
undefinedbash
undefinedInstall Wrangler CLI
安装 Wrangler CLI
npm install -g wrangler
npm install -g wrangler
Login
登录
wrangler login
wrangler login
Create new Worker
创建新的 Worker
wrangler init my-worker
wrangler init my-worker
Deploy
部署
wrangler deploy
undefinedwrangler deploy
undefinedWorkers
Workers
Basic Worker
基础 Worker
typescript
// src/index.ts
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
if (url.pathname === '/api/hello') {
return Response.json({ message: 'Hello from the edge!' });
}
return new Response('Not Found', { status: 404 });
},
};typescript
// src/index.ts
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
if (url.pathname === '/api/hello') {
return Response.json({ message: 'Hello from the edge!' });
}
return new Response('Not Found', { status: 404 });
},
};wrangler.toml Configuration
wrangler.toml 配置
toml
name = "my-worker"
main = "src/index.ts"
compatibility_date = "2024-01-01"
[vars]
ENVIRONMENT = "production"toml
name = "my-worker"
main = "src/index.ts"
compatibility_date = "2024-01-01"
[vars]
ENVIRONMENT = "production"KV Namespace
KV 命名空间
[[kv_namespaces]]
binding = "MY_KV"
id = "abc123"
[[kv_namespaces]]
binding = "MY_KV"
id = "abc123"
D1 Database
D1 数据库
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "def456"
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "def456"
R2 Bucket
R2 存储桶
[[r2_buckets]]
binding = "BUCKET"
bucket_name = "my-bucket"
[[r2_buckets]]
binding = "BUCKET"
bucket_name = "my-bucket"
AI
AI
[ai]
binding = "AI"
[ai]
binding = "AI"
Durable Objects
Durable Objects
[[durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"
[[migrations]]
tag = "v1"
new_classes = ["Counter"]
undefined[[durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"
[[migrations]]
tag = "v1"
new_classes = ["Counter"]
undefinedRequest Routing
请求路由
typescript
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
const { pathname } = url;
// Router pattern
const routes: Record<string, () => Promise<Response>> = {
'/api/users': () => handleUsers(request, env),
'/api/posts': () => handlePosts(request, env),
};
const handler = routes[pathname];
if (handler) {
return handler();
}
// Wildcard matching
if (pathname.startsWith('/api/users/')) {
const userId = pathname.split('/')[3];
return handleUser(userId, request, env);
}
return new Response('Not Found', { status: 404 });
},
};typescript
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
const { pathname } = url;
// 路由模式
const routes: Record<string, () => Promise<Response>> = {
'/api/users': () => handleUsers(request, env),
'/api/posts': () => handlePosts(request, env),
};
const handler = routes[pathname];
if (handler) {
return handler();
}
// 通配符匹配
if (pathname.startsWith('/api/users/')) {
const userId = pathname.split('/')[3];
return handleUser(userId, request, env);
}
return new Response('Not Found', { status: 404 });
},
};KV Storage
KV 存储
typescript
interface Env {
MY_KV: KVNamespace;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
// Set value
await env.MY_KV.put('key', 'value', {
expirationTtl: 3600, // 1 hour
metadata: { created: Date.now() },
});
// Get value
const value = await env.MY_KV.get('key');
// Get with metadata
const { value: data, metadata } = await env.MY_KV.getWithMetadata('key');
// List keys
const list = await env.MY_KV.list({ prefix: 'user:' });
// Delete
await env.MY_KV.delete('key');
return Response.json({ value });
},
};typescript
interface Env {
MY_KV: KVNamespace;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
// 设置值
await env.MY_KV.put('key', 'value', {
expirationTtl: 3600, // 1小时
metadata: { created: Date.now() },
});
// 获取值
const value = await env.MY_KV.get('key');
// 获取值及元数据
const { value: data, metadata } = await env.MY_KV.getWithMetadata('key');
// 列出键
const list = await env.MY_KV.list({ prefix: 'user:' });
// 删除
await env.MY_KV.delete('key');
return Response.json({ value });
},
};D1 Database (SQLite)
D1 数据库(SQLite)
typescript
interface Env {
DB: D1Database;
}
// Create tables (run once via wrangler d1 execute)
// wrangler d1 execute my-database --file=./schema.sql
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// Query
const { results } = await env.DB.prepare(
'SELECT * FROM users WHERE id = ?'
).bind(1).all();
// Insert
const { meta } = await env.DB.prepare(
'INSERT INTO users (name, email) VALUES (?, ?)'
).bind('Alice', 'alice@example.com').run();
// Batch operations
const batch = await env.DB.batch([
env.DB.prepare('INSERT INTO logs (action) VALUES (?)').bind('login'),
env.DB.prepare('UPDATE users SET last_login = ? WHERE id = ?').bind(Date.now(), 1),
]);
// First result only
const user = await env.DB.prepare(
'SELECT * FROM users WHERE email = ?'
).bind('alice@example.com').first();
return Response.json({ results, insertId: meta.last_row_id });
},
};typescript
interface Env {
DB: D1Database;
}
// 创建表(通过 wrangler d1 execute 运行一次)
// wrangler d1 execute my-database --file=./schema.sql
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// 查询
const { results } = await env.DB.prepare(
'SELECT * FROM users WHERE id = ?'
).bind(1).all();
// 插入
const { meta } = await env.DB.prepare(
'INSERT INTO users (name, email) VALUES (?, ?)'
).bind('Alice', 'alice@example.com').run();
// 批量操作
const batch = await env.DB.batch([
env.DB.prepare('INSERT INTO logs (action) VALUES (?)').bind('login'),
env.DB.prepare('UPDATE users SET last_login = ? WHERE id = ?').bind(Date.now(), 1),
]);
// 获取首个结果
const user = await env.DB.prepare(
'SELECT * FROM users WHERE email = ?'
).bind('alice@example.com').first();
return Response.json({ results, insertId: meta.last_row_id });
},
};Schema Example
示例 Schema
sql
-- schema.sql
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
title TEXT NOT NULL,
content TEXT,
FOREIGN KEY (user_id) REFERENCES users(id)
);sql
-- schema.sql
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
title TEXT NOT NULL,
content TEXT,
FOREIGN KEY (user_id) REFERENCES users(id)
);R2 Object Storage
R2 对象存储
typescript
interface Env {
BUCKET: R2Bucket;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
const key = url.pathname.slice(1);
switch (request.method) {
case 'PUT': {
// Upload file
const body = await request.arrayBuffer();
await env.BUCKET.put(key, body, {
httpMetadata: {
contentType: request.headers.get('content-type') || 'application/octet-stream',
},
customMetadata: {
uploadedBy: 'api',
},
});
return new Response('Uploaded', { status: 201 });
}
case 'GET': {
// Download file
const object = await env.BUCKET.get(key);
if (!object) {
return new Response('Not Found', { status: 404 });
}
const headers = new Headers();
object.writeHttpMetadata(headers);
headers.set('etag', object.httpEtag);
return new Response(object.body, { headers });
}
case 'DELETE': {
await env.BUCKET.delete(key);
return new Response('Deleted');
}
default:
return new Response('Method Not Allowed', { status: 405 });
}
},
};
// List objects
async function listObjects(env: Env, prefix?: string) {
const listed = await env.BUCKET.list({
prefix,
limit: 100,
});
return listed.objects.map(obj => ({
key: obj.key,
size: obj.size,
uploaded: obj.uploaded,
}));
}typescript
interface Env {
BUCKET: R2Bucket;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
const key = url.pathname.slice(1);
switch (request.method) {
case 'PUT': {
// 上传文件
const body = await request.arrayBuffer();
await env.BUCKET.put(key, body, {
httpMetadata: {
contentType: request.headers.get('content-type') || 'application/octet-stream',
},
customMetadata: {
uploadedBy: 'api',
},
});
return new Response('Uploaded', { status: 201 });
}
case 'GET': {
// 下载文件
const object = await env.BUCKET.get(key);
if (!object) {
return new Response('Not Found', { status: 404 });
}
const headers = new Headers();
object.writeHttpMetadata(headers);
headers.set('etag', object.httpEtag);
return new Response(object.body, { headers });
}
case 'DELETE': {
await env.BUCKET.delete(key);
return new Response('Deleted');
}
default:
return new Response('Method Not Allowed', { status: 405 });
}
},
};
// 列出对象
async function listObjects(env: Env, prefix?: string) {
const listed = await env.BUCKET.list({
prefix,
limit: 100,
});
return listed.objects.map(obj => ({
key: obj.key,
size: obj.size,
uploaded: obj.uploaded,
}));
}Cloudflare AI
Cloudflare AI
typescript
interface Env {
AI: Ai;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const { prompt } = await request.json();
// Text generation (Llama, Mistral, etc.)
const response = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: prompt },
],
max_tokens: 1024,
});
return Response.json(response);
},
};
// Image generation
async function generateImage(env: Env, prompt: string) {
const response = await env.AI.run('@cf/stabilityai/stable-diffusion-xl-base-1.0', {
prompt,
num_steps: 20,
});
return new Response(response, {
headers: { 'content-type': 'image/png' },
});
}
// Text embeddings
async function getEmbeddings(env: Env, text: string) {
const response = await env.AI.run('@cf/baai/bge-base-en-v1.5', {
text: [text],
});
return response.data[0]; // Float32Array
}
// Image classification
async function classifyImage(env: Env, imageData: ArrayBuffer) {
const response = await env.AI.run('@cf/microsoft/resnet-50', {
image: [...new Uint8Array(imageData)],
});
return response;
}
// Speech to text
async function transcribe(env: Env, audioData: ArrayBuffer) {
const response = await env.AI.run('@cf/openai/whisper', {
audio: [...new Uint8Array(audioData)],
});
return response.text;
}typescript
interface Env {
AI: Ai;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const { prompt } = await request.json();
// 文本生成(Llama、Mistral等)
const response = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: prompt },
],
max_tokens: 1024,
});
return Response.json(response);
},
};
// 图片生成
async function generateImage(env: Env, prompt: string) {
const response = await env.AI.run('@cf/stabilityai/stable-diffusion-xl-base-1.0', {
prompt,
num_steps: 20,
});
return new Response(response, {
headers: { 'content-type': 'image/png' },
});
}
// 文本嵌入
async function getEmbeddings(env: Env, text: string) {
const response = await env.AI.run('@cf/baai/bge-base-en-v1.5', {
text: [text],
});
return response.data[0]; // Float32Array
}
// 图片分类
async function classifyImage(env: Env, imageData: ArrayBuffer) {
const response = await env.AI.run('@cf/microsoft/resnet-50', {
image: [...new Uint8Array(imageData)],
});
return response;
}
// 语音转文本
async function transcribe(env: Env, audioData: ArrayBuffer) {
const response = await env.AI.run('@cf/openai/whisper', {
audio: [...new Uint8Array(audioData)],
});
return response.text;
}Durable Objects
Durable Objects
typescript
// Durable Object class
export class Counter {
state: DurableObjectState;
constructor(state: DurableObjectState) {
this.state = state;
}
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
let value = (await this.state.storage.get<number>('count')) || 0;
switch (url.pathname) {
case '/increment':
value++;
await this.state.storage.put('count', value);
break;
case '/decrement':
value--;
await this.state.storage.put('count', value);
break;
}
return Response.json({ count: value });
}
}
// Worker using Durable Object
interface Env {
COUNTER: DurableObjectNamespace;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// Get unique ID for this counter (e.g., per user)
const counterId = env.COUNTER.idFromName('global-counter');
const counter = env.COUNTER.get(counterId);
// Forward request to Durable Object
return counter.fetch(request);
},
};typescript
// Durable Object 类
export class Counter {
state: DurableObjectState;
constructor(state: DurableObjectState) {
this.state = state;
}
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
let value = (await this.state.storage.get<number>('count')) || 0;
switch (url.pathname) {
case '/increment':
value++;
await this.state.storage.put('count', value);
break;
case '/decrement':
value--;
await this.state.storage.put('count', value);
break;
}
return Response.json({ count: value });
}
}
// 使用 Durable Object 的 Worker
interface Env {
COUNTER: DurableObjectNamespace;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// 获取此计数器的唯一ID(例如,按用户区分)
const counterId = env.COUNTER.idFromName('global-counter');
const counter = env.COUNTER.get(counterId);
// 将请求转发到 Durable Object
return counter.fetch(request);
},
};Cloudflare Pages
Cloudflare Pages
pages.toml (Functions Config)
pages.toml(函数配置)
toml
[build]
command = "npm run build"
output_directory = "dist"
[[redirects]]
from = "/old-page"
to = "/new-page"
status = 301
[[headers]]
for = "/api/*"
[headers.values]
Access-Control-Allow-Origin = "*"toml
[build]
command = "npm run build"
output_directory = "dist"
[[redirects]]
from = "/old-page"
to = "/new-page"
status = 301
[[headers]]
for = "/api/*"
[headers.values]
Access-Control-Allow-Origin = "*"Pages Functions
Pages 函数
typescript
// functions/api/hello.ts
export const onRequestGet: PagesFunction = async (context) => {
return Response.json({ message: 'Hello!' });
};
export const onRequestPost: PagesFunction<Env> = async (context) => {
const body = await context.request.json();
// Access bindings
await context.env.KV.put('key', JSON.stringify(body));
return Response.json({ success: true });
};
// functions/api/users/[id].ts
export const onRequestGet: PagesFunction = async (context) => {
const userId = context.params.id;
return Response.json({ userId });
};
// Middleware: functions/_middleware.ts
export const onRequest: PagesFunction = async (context) => {
// Auth check
const auth = context.request.headers.get('Authorization');
if (!auth) {
return new Response('Unauthorized', { status: 401 });
}
// Continue to next handler
return context.next();
};typescript
// functions/api/hello.ts
export const onRequestGet: PagesFunction = async (context) => {
return Response.json({ message: 'Hello!' });
};
export const onRequestPost: PagesFunction<Env> = async (context) => {
const body = await context.request.json();
// 访问绑定资源
await context.env.KV.put('key', JSON.stringify(body));
return Response.json({ success: true });
};
// functions/api/users/[id].ts
export const onRequestGet: PagesFunction = async (context) => {
const userId = context.params.id;
return Response.json({ userId });
};
// 中间件:functions/_middleware.ts
export const onRequest: PagesFunction = async (context) => {
// 权限校验
const auth = context.request.headers.get('Authorization');
if (!auth) {
return new Response('Unauthorized', { status: 401 });
}
// 继续执行下一个处理器
return context.next();
};Queues
队列
typescript
// Producer
interface Env {
MY_QUEUE: Queue;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// Send message to queue
await env.MY_QUEUE.send({
type: 'email',
to: 'user@example.com',
subject: 'Welcome!',
});
// Batch send
await env.MY_QUEUE.sendBatch([
{ body: { task: 'process', id: 1 } },
{ body: { task: 'process', id: 2 } },
]);
return Response.json({ queued: true });
},
};
// Consumer
export default {
async queue(batch: MessageBatch<any>, env: Env): Promise<void> {
for (const message of batch.messages) {
try {
await processMessage(message.body);
message.ack();
} catch (error) {
message.retry();
}
}
},
};typescript
// 生产者
interface Env {
MY_QUEUE: Queue;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// 发送消息到队列
await env.MY_QUEUE.send({
type: 'email',
to: 'user@example.com',
subject: 'Welcome!',
});
// 批量发送
await env.MY_QUEUE.sendBatch([
{ body: { task: 'process', id: 1 } },
{ body: { task: 'process', id: 2 } },
]);
return Response.json({ queued: true });
},
};
// 消费者
export default {
async queue(batch: MessageBatch<any>, env: Env): Promise<void> {
for (const message of batch.messages) {
try {
await processMessage(message.body);
message.ack();
} catch (error) {
message.retry();
}
}
},
};Cron Triggers
Cron 触发器
toml
undefinedtoml
undefinedwrangler.toml
wrangler.toml
[triggers]
crons = ["0 0 * * ", "/15 * * * *"] # Daily at midnight, every 15 min
```typescript
export default {
async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext): Promise<void> {
switch (event.cron) {
case '0 0 * * *':
await dailyCleanup(env);
break;
case '*/15 * * * *':
await checkHealthStatus(env);
break;
}
},
};[triggers]
crons = ["0 0 * * ", "/15 * * * *"] # 每日午夜,每15分钟一次
```typescript
export default {
async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext): Promise<void> {
switch (event.cron) {
case '0 0 * * *':
await dailyCleanup(env);
break;
case '*/15 * * * *':
await checkHealthStatus(env);
break;
}
},
};WebSockets
WebSockets
typescript
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const upgradeHeader = request.headers.get('Upgrade');
if (upgradeHeader === 'websocket') {
const [client, server] = Object.values(new WebSocketPair());
server.accept();
server.addEventListener('message', (event) => {
server.send(`Echo: ${event.data}`);
});
return new Response(null, {
status: 101,
webSocket: client,
});
}
return new Response('Expected WebSocket', { status: 400 });
},
};typescript
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const upgradeHeader = request.headers.get('Upgrade');
if (upgradeHeader === 'websocket') {
const [client, server] = Object.values(new WebSocketPair());
server.accept();
server.addEventListener('message', (event) => {
server.send(`Echo: ${event.data}`);
});
return new Response(null, {
status: 101,
webSocket: client,
});
}
return new Response('Expected WebSocket', { status: 400 });
},
};Resources
资源
- Workers Docs: https://developers.cloudflare.com/workers/
- D1 Docs: https://developers.cloudflare.com/d1/
- R2 Docs: https://developers.cloudflare.com/r2/
- Pages Docs: https://developers.cloudflare.com/pages/
- AI Docs: https://developers.cloudflare.com/workers-ai/
- Wrangler CLI: https://developers.cloudflare.com/workers/wrangler/
- Workers 文档: https://developers.cloudflare.com/workers/
- D1 文档: https://developers.cloudflare.com/d1/
- R2 文档: https://developers.cloudflare.com/r2/
- Pages 文档: https://developers.cloudflare.com/pages/
- AI 文档: https://developers.cloudflare.com/workers-ai/
- Wrangler CLI: https://developers.cloudflare.com/workers/wrangler/