名称: Bun Cloudflare Workers 描述: 当用户询问关于"使用Bun的Cloudflare Workers"、“将Bun部署到Workers”、“使用Bun的wrangler”、“边缘部署”、"Bun到Cloudflare"或使用Bun构建和部署应用到Cloudflare Workers时,应使用此技能。
Bun Cloudflare Workers
使用Bun进行开发,构建和部署Cloudflare Workers。
快速开始
# 创建新的Workers项目
bunx create-cloudflare my-worker
cd my-worker
# 安装依赖
bun install
# 开发
bun run dev
# 部署
bun run deploy
项目设置
package.json
{
"scripts": {
"dev": "wrangler dev",
"deploy": "wrangler deploy",
"build": "bun build src/index.ts --outdir=dist --target=browser"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20250906.0",
"wrangler": "^4.54.0"
}
}
wrangler.toml
name = "my-worker"
main = "src/index.ts"
compatibility_date = "2024-01-01"
# 使用Bun进行本地开发
[dev]
local_protocol = "http"
# 绑定
[[kv_namespaces]]
binding = "KV"
id = "xxx"
[[d1_databases]]
binding = "DB"
database_name = "my-db"
database_id = "xxx"
基本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 === "/") {
return new Response("来自Cloudflare Workers的问候!");
}
if (url.pathname === "/api/data") {
return Response.json({ message: "Hello" });
}
return new Response("未找到", { status: 404 });
},
};
interface Env {
KV: KVNamespace;
DB: D1Database;
}
使用Hono
// src/index.ts
import { Hono } from "hono";
type Bindings = {
KV: KVNamespace;
DB: D1Database;
};
const app = new Hono<{ Bindings: Bindings }>();
app.get("/", (c) => c.text("Hello Hono!"));
app.get("/api/users", async (c) => {
const users = await c.env.DB.prepare("SELECT * FROM users").all();
return c.json(users.results);
});
app.post("/api/users", async (c) => {
const { name } = await c.req.json();
await c.env.DB.prepare("INSERT INTO users (name) VALUES (?)").bind(name).run();
return c.json({ success: true });
});
export default app;
KV存储
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
const key = url.searchParams.get("key");
if (request.method === "GET" && key) {
const value = await env.KV.get(key);
return Response.json({ key, value });
}
if (request.method === "PUT" && key) {
const value = await request.text();
await env.KV.put(key, value, { expirationTtl: 3600 });
return Response.json({ success: true });
}
return new Response("错误请求", { status: 400 });
},
};
D1数据库
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// 查询
const { results } = await env.DB.prepare(
"SELECT * FROM users WHERE active = ?"
).bind(1).all();
// 插入
const info = 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 users (name) VALUES (?)").bind("Bob"),
env.DB.prepare("INSERT INTO users (name) VALUES (?)").bind("Charlie"),
]);
return Response.json(results);
},
};
持久对象
// src/counter.ts
export class Counter {
private state: DurableObjectState;
private value = 0;
constructor(state: DurableObjectState) {
this.state = state;
this.state.blockConcurrencyWhile(async () => {
this.value = (await this.state.storage.get("value")) || 0;
});
}
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
if (url.pathname === "/increment") {
this.value++;
await this.state.storage.put("value", this.value);
}
return Response.json({ value: this.value });
}
}
// src/index.ts
export { Counter } from "./counter";
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const id = env.COUNTER.idFromName("global");
const stub = env.COUNTER.get(id);
return stub.fetch(request);
},
};
# wrangler.toml
[[durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"
[[migrations]]
tag = "v1"
new_classes = ["Counter"]
R2存储
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
const key = url.pathname.slice(1);
if (request.method === "GET") {
const object = await env.BUCKET.get(key);
if (!object) {
return new Response("未找到", { status: 404 });
}
return new Response(object.body, {
headers: { "Content-Type": object.httpMetadata?.contentType || "application/octet-stream" },
});
}
if (request.method === "PUT") {
await env.BUCKET.put(key, request.body, {
httpMetadata: { contentType: request.headers.get("Content-Type") || undefined },
});
return Response.json({ success: true });
}
return new Response("方法不允许", { status: 405 });
},
};
使用Bun开发
本地开发
# 使用wrangler运行(使用Bun进行TypeScript)
bun run dev
# 或直接
bunx wrangler dev
使用Bun测试
// src/index.test.ts
import { describe, test, expect } from "bun:test";
// 模拟worker
const worker = {
async fetch(request: Request) {
return new Response("Hello");
},
};
describe("Worker", () => {
test("返回hello", async () => {
const request = new Request("http://localhost/");
const response = await worker.fetch(request);
expect(await response.text()).toBe("Hello");
});
});
使用Miniflare测试
import { Miniflare } from "miniflare";
const mf = new Miniflare({
script: await Bun.file("./dist/index.js").text(),
kvNamespaces: ["KV"],
});
const response = await mf.dispatchFetch("http://localhost/");
console.log(await response.text());
生产构建
// build.ts
await Bun.build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
target: "browser", // Workers使用浏览器API
minify: true,
sourcemap: "external",
});
bun run build.ts
bunx wrangler deploy
环境变量
# wrangler.toml
[vars]
API_URL = "https://api.example.com"
# 秘密(通过CLI设置)
# wrangler secret put API_KEY
export default {
async fetch(request: Request, env: Env): Promise<Response> {
console.log(env.API_URL); // 来自vars
console.log(env.API_KEY); // 来自secrets
return new Response("OK");
},
};
计划Worker(Cron)
export default {
async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext): Promise<void> {
console.log("Cron触发于:", event.scheduledTime);
// 执行计划任务
await env.DB.prepare("DELETE FROM logs WHERE created_at < ?")
.bind(Date.now() - 7 * 24 * 60 * 60 * 1000)
.run();
},
async fetch(request: Request, env: Env): Promise<Response> {
return new Response("OK");
},
};
# wrangler.toml
[triggers]
crons = ["0 * * * *"] # 每小时
常见错误
| 错误 | 原因 | 修复 |
|---|---|---|
Bun API不可用 |
Workers使用V8 | 仅使用Web API |
模块未找到 |
构建问题 | 检查打包器配置 |
脚本过大 |
超过10MB | 优化打包 |
CPU时间超限 |
执行时间过长 | 优化或使用队列 |
API兼容性
Workers支持Web API,不支持Bun特定API:
| 可用 | 不可用 |
|---|---|
| fetch() | Bun.file() |
| Response | Bun.serve() |
| Request | bun:sqlite |
| URL | bun:ffi |
| crypto | fs |
| TextEncoder | child_process |
何时加载参考
加载references/bindings.md当:
- 高级KV/D1/R2模式
- 队列worker
- 服务绑定
加载references/performance.md当:
- 打包优化
- 减少冷启动
- 缓存策略