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 做生产项目”了。