Wrangler
如何搭建一个真实一点的 API:我的 Worker 是什么、要连接哪些 Cloudflare 资源、不同环境怎么隔离、怎么部署
Wrangler
wrangler.jsonc 是理解 Wrangler 的关键之一。
我建议不要把它理解成“Wrangler 的配置文件”这么简单,而是把它看成:
“告诉 Wrangler:我的 Worker 是什么、要连接哪些 Cloudflare 资源、不同环境怎么隔离、怎么部署。”
1. 先看一个完整例子
假设我们做一个真实一点的 API:
my-api/
├── src/
│ └── index.ts
├── migrations/
│ ├── 0001_init.sql
│ └── 0002_add_profile.sql
├── wrangler.jsonc
├── package.json
└── tsconfig.json一个比较典型的 wrangler.jsonc:
{
"name": "my-api",
"main": "src/index.ts",
"compatibility_date": "2026-09-15",
"vars": {
"APP_ENV": "production"
},
"d1_databases": [
{
"binding": "DB",
"database_name": "my-api-db",
"database_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"migrations_dir": "migrations"
}
],
"r2_buckets": [
{
"binding": "BUCKET",
"bucket_name": "my-api-files"
}
]
}先别急着记字段。
我们逐个拆。
2. name
{
"name": "my-api"
}这是 Worker 的名字。
最终 Cloudflare 上会有一个 Worker:
my-api例如部署:
npx wrangler deployWrangler 就知道:
我要把这个项目部署成 my-api 这个 Worker。
3. main
{
"main": "src/index.ts"
}告诉 Wrangler:
Worker 的入口文件在哪里?
例如:
src/index.ts里面:
export default {
async fetch(request, env) {
return new Response("Hello");
},
};所以:
wrangler.jsonc
│
│ main
▼
src/index.ts
│
▼
Worker4. compatibility_date
这是一个非常重要但经常被忽略的字段。
{
"compatibility_date": "2026-09-15"
}它不是:
“Worker 只在 2026-09-15 工作。”
而更像:
“告诉 Cloudflare,我希望 Worker Runtime 按这个日期对应的兼容行为运行。”
Cloudflare Workers 的 Runtime 会持续变化。
例如未来 Cloudflare 改变某个 API 行为:
旧行为 ────────────────> 新行为如果你的 Worker 没有明确 compatibility date,就可能受到 Runtime 行为变化的影响。
指定:
"compatibility_date": "2026-09-15"相当于给项目建立一个兼容性基线。
5. vars
例如:
{
"vars": {
"APP_ENV": "production",
"API_VERSION": "v1"
}
}代码里:
interface Env {
APP_ENV: string;
API_VERSION: string;
}
export default {
async fetch(request, env: Env) {
console.log(env.APP_ENV);
return Response.json({
version: env.API_VERSION,
});
},
};也就是:
wrangler.jsonc
│
│ vars
▼
Worker
│
▼
env.APP_ENV
env.API_VERSION6. 但是 Secret 不应该放 vars
这是非常重要的。
不要这样:
{
"vars": {
"STRIPE_SECRET_KEY": "sk_xxxxxxxxx"
}
}因为 vars 是普通配置。
对于:
API Key
Database password
JWT secret
Stripe secret
OAuth secret应该使用 Secret:
npx wrangler secret put STRIPE_SECRET_KEY然后代码:
env.STRIPE_SECRET_KEY所以可以记成:
普通配置
↓
vars
敏感信息
↓
wrangler secret7. 最重要的:Bindings
如果你只记住 Wrangler 一个概念,我建议就是:
Binding
例如 D1:
{
"d1_databases": [
{
"binding": "DB",
"database_name": "my-api-db",
"database_id": "xxxxxxxx"
}
]
}这里:
"binding": "DB"意味着:
Cloudflare D1
│
▼
DB
│
▼
env.DBWorker:
env.DB就可以访问 D1。
8. D1 的配置
完整一点:
"d1_databases": [
{
"binding": "DB",
"database_name": "my-api-db",
"database_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"migrations_dir": "migrations"
}
]分别是什么?
binding
"binding": "DB"代码里的:
env.DBdatabase_name
"database_name": "my-api-db"Cloudflare D1 的名字。
database_id
"database_id": "xxxxxxxx"Cloudflare 创建 D1 时给你的唯一 ID。
例如:
npx wrangler d1 create my-api-db会返回它。
migrations_dir
"migrations_dir": "migrations"告诉 Wrangler:
migrations/
├── 0001_init.sql
├── 0002_add_user.sql
└── 0003_add_index.sqlMigration 在哪里。
9. R2 也是 Binding
假设你有一个 R2 Bucket:
my-api-files配置:
"r2_buckets": [
{
"binding": "BUCKET",
"bucket_name": "my-api-files"
}
]代码:
await env.BUCKET.put(
"hello.txt",
"Hello World"
);读取:
const object = await env.BUCKET.get("hello.txt");所以:
R2 Bucket
│
▼
BUCKET
│
▼
env.BUCKET10. KV
KV 类似:
"kv_namespaces": [
{
"binding": "CACHE",
"id": "xxxxxxxxxxxxxxxx"
}
]代码:
await env.CACHE.put(
"user:123",
"Alice"
);读取:
const value = await env.CACHE.get("user:123");又是同一个思想:
Cloudflare Resource
│
▼
binding
│
▼
env.X11. Durable Objects
Durable Objects 稍微特殊一点。
例如:
{
"durable_objects": {
"bindings": [
{
"name": "CHAT",
"class_name": "ChatRoom"
}
]
}
}然后代码里:
env.CHAT拿到 Durable Object namespace。
这里会涉及:
Durable Object
│
├── Worker binding
│
└── class如果开始使用 DO,还需要考虑 migration,因为 Durable Objects 的 class 需要版本迁移。
12. wrangler.jsonc 真正厉害的地方:Environment
这才是生产项目里非常重要的一部分。
假设:
开发环境
development
测试环境
staging
生产环境
production你绝对不希望:
本地开发
│
▼
Production D1然后一个:
DROP TABLE users;把生产搞炸。
所以我们需要环境隔离。
13. Environment 的基本思想
可以这样:
{
"name": "my-api",
"main": "src/index.ts",
"env": {
"staging": {
"name": "my-api-staging"
},
"production": {
"name": "my-api-production"
}
}
}于是:
npx wrangler deploy --env staging部署:
my-api-staging而:
npx wrangler deploy --env production部署:
my-api-production14. 更实际的设计
真正项目通常是:
Git
│
┌──────────┴──────────┐
│ │
staging production
│ │
▼ ▼
Worker staging Worker production
│ │
▼ ▼
D1 staging D1 production比如:
{
"name": "my-api",
"main": "src/index.ts",
"compatibility_date": "2026-09-15",
"env": {
"staging": {
"name": "my-api-staging",
"vars": {
"APP_ENV": "staging"
},
"d1_databases": [
{
"binding": "DB",
"database_name": "my-api-staging-db",
"database_id": "STAGING_DATABASE_ID",
"migrations_dir": "migrations"
}
]
},
"production": {
"name": "my-api-production",
"vars": {
"APP_ENV": "production"
},
"d1_databases": [
{
"binding": "DB",
"database_name": "my-api-production-db",
"database_id": "PRODUCTION_DATABASE_ID",
"migrations_dir": "migrations"
}
]
}
}
}注意一个非常漂亮的地方:
代码完全不用改变。
代码永远:
env.DB但是:
staging
│
▼
env.DB
│
▼
staging D1生产:
production
│
▼
env.DB
│
▼
production D1这就是 Binding 的价值。
15. wrangler dev 又怎么知道环境?
例如:
npx wrangler dev默认开发。
如果:
npx wrangler dev --env staging就是 staging 环境。
部署同理:
npx wrangler deploy --env staging和:
npx wrangler deploy --env production对应不同环境。
16. 我比较推荐的项目结构
如果你以后认真做 Cloudflare 项目,我比较推荐:
my-api/
│
├── src/
│ ├── index.ts
│ ├── routes/
│ │ ├── users.ts
│ │ └── auth.ts
│ ├── services/
│ └── types.ts
│
├── migrations/
│ ├── 0001_init.sql
│ ├── 0002_users.sql
│ └── 0003_indexes.sql
│
├── wrangler.jsonc
├── package.json
├── tsconfig.json
└── README.md而不是:
dev-wrangler.json
prod-wrangler.json
staging-wrangler.json我通常更推荐一个 wrangler.jsonc + 多个 environment。
17. 一个比较完整的生产级例子
可以把它理解成这样:
{
"name": "my-api",
"main": "src/index.ts",
"compatibility_date": "2026-09-15",
"observability": {
"enabled": true
},
"env": {
"staging": {
"name": "my-api-staging",
"vars": {
"APP_ENV": "staging"
},
"d1_databases": [
{
"binding": "DB",
"database_name": "my-api-staging-db",
"database_id": "STAGING_ID",
"migrations_dir": "migrations"
}
],
"r2_buckets": [
{
"binding": "BUCKET",
"bucket_name": "my-api-staging-files"
}
]
},
"production": {
"name": "my-api-production",
"vars": {
"APP_ENV": "production"
},
"d1_databases": [
{
"binding": "DB",
"database_name": "my-api-production-db",
"database_id": "PRODUCTION_ID",
"migrations_dir": "migrations"
}
],
"r2_buckets": [
{
"binding": "BUCKET",
"bucket_name": "my-api-production-files"
}
]
}
}
}这样整个系统就很清楚:
wrangler.jsonc
│
┌────────────┴────────────┐
│ │
staging production
│ │
┌─────┴─────┐ ┌─────┴─────┐
│ │ │ │
Worker D1 Worker D1
│ │ │ │
│ R2 │ R2
│ │
└──── env ────┘ └──── env ────┘18. 有一个坑:环境不是“完全复制”
这是很多刚接触 Wrangler 的人容易踩的坑。
你写:
"env": {
"production": {
"name": "my-api-production"
}
}不要简单理解成:
production 自动继承根配置里的所有东西。
Wrangler 的 environment 配置存在一些继承/非继承规则,尤其是 bindings、routes、triggers 等配置,实际设计时不能想当然地认为所有字段都会自动继承。
所以我的建议是:
生产项目里,关键资源 binding 在 environment 下明确写出来。
例如:
"production": {
"d1_databases": [
{
"binding": "DB",
"database_name": "my-api-production-db",
"database_id": "..."
}
]
}这样看到配置就知道生产到底连接哪个数据库。
19. 最后建立一个“脑模型”
以后看到:
{
"name": "...",
"main": "...",
"vars": {},
"d1_databases": [],
"r2_buckets": [],
"kv_namespaces": [],
"durable_objects": {},
"env": {}
}不要把它看成一堆 JSON。
把它翻译成人话:
Wrangler
│
“我要部署什么?”
│
┌──────────────┼──────────────┐
│ │ │
name main compatibility
│ │
▼ ▼
Worker 入口代码
│
▼
┌───────────┐
│ bindings │
└─────┬─────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
D1 R2 KV
│ │ │
DB BUCKET CACHE
│ │ │
└───────────┼───────────┘
▼
env.X
env
│
┌───────┴───────┐
▼ ▼
staging production这就是 wrangler.jsonc 的核心。
如果你接下来要做真实项目,我建议下一步重点搞懂 wrangler.jsonc + env + D1 migration + Secret 四者是怎么配合的。尤其是一个常见的生产工作流:
Git push
↓
GitHub Actions
↓
staging Worker + staging D1
↓
测试
↓
production migration
↓
production Worker这一步弄明白之后,你基本就从“会用 Wrangler”进入“会用 Wrangler 做生产项目”了。
Related Posts
什么是 Harness
模型只会生成文本。Harness 是把其中一部分文本变成工具调用、真正执行,再把结果送回模型的那一层运行时。
拆解 OpenAI Pando:用因果一致性和可复用 packfile 把 Git 扩到 agent 规模
OpenAI 的 Git 后端 Pando 把写入降为按 ref 串行化、只对 ref 指针做 CAS,读取则复用推送时的 pack、通过 Git 协议 v2 的 packfile-uri 从区域缓存分发。后台用类似 LSM 的分层压实,让拉取规划做到 O(log Δ)。
RSC
React Server Components (RSC) in Next.js are components that render exclusively on the server, making them the default component type in the App Router.