名称: cloudflare 描述: 在Cloudflare的边缘平台上构建和部署。使用在创建Workers、Pages、D1数据库、R2存储、AI推理或KV存储时。触发于Cloudflare、Workers、Cloudflare Pages、D1、R2、KV、Cloudflare AI、Durable Objects、边缘计算。
Cloudflare平台
在Cloudflare的边缘网络上构建全球分布式应用程序。
快速开始
# 安装Wrangler CLI
npm install -g wrangler
# 登录
wrangler login
# 创建新的Worker
wrangler init my-worker
# 部署
wrangler deploy
Workers
基本Worker
// 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配置
name = "my-worker"
main = "src/index.ts"
compatibility_date = "2024-01-01"
[vars]
ENVIRONMENT = "production"
# KV命名空间
[[kv_namespaces]]
binding = "MY_KV"
id = "abc123"
# D1数据库
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "def456"
# R2存储桶
[[r2_buckets]]
binding = "BUCKET"
bucket_name = "my-bucket"
# AI
[ai]
binding = "AI"
# Durable Objects
[[durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"
[[migrations]]
tag = "v1"
new_classes = ["Counter"]
请求路由
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存储
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数据库 (SQLite)
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.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对象存储
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
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: '你是一个有用的助手。' },
{ 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 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 });
}
}
// Worker使用Durable Object
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
pages.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/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
// 生产者
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触发器
# wrangler.toml
[triggers]
crons = ["0 0 * * *", "*/15 * * * *"] # 每天午夜,每15分钟
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
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 });
},
};
资源
- 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/