你可以在部署到 Cloudflare 网络之前,在自己的本地机器上构建、运行和测试 Worker 代码。这得益于 Miniflare——一个使用与生产环境相同的运行时 workerd ↗ 来执行 Worker 代码的模拟器。
默认情况下,Worker 的绑定(binding)连接到本地模拟资源,但可配置为通过远程绑定(remote bindings)与真实的生产资源交互。
开发 Workers 时,理解两个不同的概念很重要:
-
Worker 执行:Worker 代码实际运行的位置(本地机器 vs Cloudflare 基础设施)。
-
绑定(Bindings):Worker 如何与 Cloudflare 资源交互(如 KV 命名空间、R2 存储桶、D1 数据库、Queues、Durable Objects 等)。在 Worker 代码中,这些通过
env对象访问(例如env.MY_KV)。
你可以通过以下方式启动本地开发服务器:
- Cloudflare Workers CLI Wrangler,使用内置
wrangler dev命令。
npx wrangler devyarn wrangler devpnpm wrangler devnpx vite devyarn vite devpnpm vite devWrangler 和 Cloudflare Vite 插件底层都使用 Miniflare,并由 Cloudflare 团队开发和维护。关于何时使用 Wrangler 与 Vite 的指南,请参阅 在 Wrangler 与 Vite 之间选择。
默认情况下,运行 wrangler dev / vite dev(使用 Vite 插件 时)意味着:
- Worker 代码在本地机器上运行。
- Wrangler 配置 中 Worker 绑定的所有资源都在本地模拟。
- 本地
workerd运行时使用TZ=UTC,因此 Worker 内的Date和IntlAPI 使用 UTC,与生产 Cloudflare 运行时一致,不受机器时区影响。
绑定(Bindings) 是允许 Worker 与各种 Cloudflare 资源交互的接口(如 KV 命名空间、R2 存储桶、D1 数据库、Queues、Durable Objects 等)。在 Worker 代码中,这些通过 env 对象访问(例如 env.MY_KV)。
在本地开发期间,Worker 代码使用与已部署环境完全相同的 API 调用(例如 env.MY_KV.put())与这些绑定交互。这些本地资源初始为空,但你可以按 添加本地数据 中的说明填充数据。
- 默认情况下,绑定连接到本地资源模拟(AI 绑定(binding) 除外,AI 模型始终在远程运行)。
- 你可以覆盖此默认行为,通过远程绑定(remote bindings)按绑定连接到远程资源。这样可以在 Worker 代码仍在本地运行的同时连接到真实的生产资源。
- 使用
wrangler dev时,可以通过提供--local标志(即wrangler dev --local)临时禁用所有远程绑定(remote bindings)(仅连接到本地资源)
远程绑定(Remote bindings) 是在本地开发期间配置为连接到已部署的远程资源,而不是本地模拟资源的绑定。远程绑定由 Wrangler、Cloudflare Vite 插件 和 @cloudflare/vitest-pool-workers 包支持。你可以在绑定定义中设置 remote: true 来配置远程绑定。
{
"name": "my-worker",
// Set this to today's date
"compatibility_date": "2026-08-17",
"r2_buckets": [
{
"bucket_name": "screenshots-bucket",
"binding": "screenshots_bucket",
"remote": true,
},
],
}name = "my-worker"
# Set this to today's date
compatibility_date = "2026-08-17"
[[r2_buckets]]
bucket_name = "screenshots-bucket"
binding = "screenshots_bucket"
remote = true配置远程绑定时,Worker 仍然在本地执行,只有绑定连接的底层资源发生变化。对于所有标记为 remote: true 的绑定,Miniflare 会将其操作(例如 env.MY_KV.put())路由到已部署的资源。其他未明确配置 remote: true 的绑定继续使用默认的本地模拟。
远程绑定可与 Workers 环境 很好地配合使用。为保护生产数据,你可以创建开发或 staging 环境,并在 Wrangler 配置 中指定与生产环境不同的资源。
例如:
{
"name": "my-worker",
// Set this to today's date
"compatibility_date": "2026-08-17",
"env": {
"production": {
"r2_buckets": [
{
"bucket_name": "screenshots-bucket",
"binding": "screenshots_bucket",
},
],
},
"staging": {
"r2_buckets": [
{
"bucket_name": "preview-screenshots-bucket",
"binding": "screenshots_bucket",
"remote": true,
},
],
},
},
}name = "my-worker"
# Set this to today's date
compatibility_date = "2026-08-17"
[[env.production.r2_buckets]]
bucket_name = "screenshots-bucket"
binding = "screenshots_bucket"
[[env.staging.r2_buckets]]
bucket_name = "preview-screenshots-bucket"
binding = "screenshots_bucket"
remote = true使用上述配置运行 wrangler dev -e staging(或 CLOUDFLARE_ENV=staging vite dev)意味着:
- Worker 代码在本地运行
- 所有对
env.screenshots_bucket的调用将使用preview-screenshots-bucket资源,而不是生产环境的screenshots-bucket。
我们建议将特定绑定配置为连接到其远程对应资源。这些服务通常依赖 Cloudflare 的网络基础设施或具有无法完全在本地模拟的复杂后端。
以下绑定建议在 Wrangler 配置中设置 remote: true:
与真实的无头浏览器交互以进行渲染。Browser Run 目前没有本地模拟。
{
"browser": {
"binding": "MY_BROWSER",
"remote": true
},
}[browser]
binding = "MY_BROWSER"
remote = true使用部署在 Cloudflare 网络上的实际 AI 模型进行推理。Workers AI 目前没有本地模拟。
{
"ai": {
"binding": "AI",
"remote": true
},
}[ai]
binding = "AI"
remote = true连接到生产 Vectorize 索引以进行准确的向量搜索和相似度操作。Vectorize 目前没有本地模拟。
{
"vectorize": [
{
"binding": "MY_VECTORIZE_INDEX",
"index_name": "my-prod-index",
"remote": true
}
],
}[[vectorize]]
binding = "MY_VECTORIZE_INDEX"
index_name = "my-prod-index"
remote = truemTLS:
验证证书交换和验证流程是否按预期工作。mTLS 绑定目前没有本地模拟。
{
"mtls_certificates": [
{
"binding": "MY_CLIENT_CERT_FETCHER",
"certificate_id": "<YOUR_UPLOADED_CERT_ID>",
"remote": true
}
]
}[[mtls_certificates]]
binding = "MY_CLIENT_CERT_FETCHER"
certificate_id = "<YOUR_UPLOADED_CERT_ID>"
remote = true连接到高保真版本的 Images API,并验证所有转换是否按预期工作。Cloudflare Images 的本地模拟功能有限,仅支持部分特性。
{
"images": {
"binding": "IMAGES" ,
"remote": true
}
}[images]
binding = "IMAGES"
remote = trueWorkers for Platforms 用户可以在 dispatch namespace 绑定定义中配置 remote: true:
{
"dispatch_namespaces": [
{
"binding": "DISPATCH_NAMESPACE",
"namespace": "testing",
"remote":true
}
]
}[[dispatch_namespaces]]
binding = "DISPATCH_NAMESPACE"
namespace = "testing"
remote = true这允许你在本地运行 dynamic dispatch Worker,同时连接到远程 dispatch namespace 绑定。这样你可以针对真实、已部署的 user Workers 测试核心调度逻辑的更改。
某些绑定在本地开发期间不支持远程连接(即 remote: true)。这些将始终使用本地模拟或本地值。
如果在 Wrangler 配置中为以下任何不支持的绑定类型指定 remote: true,Cloudflare 会发出错误。请参阅远程绑定支持和不支持的所有绑定。
-
Durable Objects:未来可能支持 Durable Objects 的远程连接,但目前始终本地运行。不过,可以将 Durable Objects 与远程绑定结合使用。请参阅下方的 将远程资源与 Durable Objects 和 Workflows 配合使用。
-
Workflows:未来可能支持 Workflows 的远程连接,但目前仅本地运行。不过,可以将 Workflows 与远程绑定结合使用。请参阅下方的 将远程资源与 Durable Objects 和 Workflows 配合使用。
-
环境变量(
vars):环境变量旨在在本地开发与已部署环境之间保持不同。它们可在本地轻松配置(例如在.dev.vars文件中或直接在 Wrangler 配置中)。 -
Secrets:与环境变量类似,出于安全原因,secrets 在本地开发与已部署环境中预期具有不同的值。使用
.dev.vars进行本地 secret 管理。 -
Static Assets 静态资源在开发期间始终从本地磁盘提供,以获得速度和对更改的直接反馈。
-
Version Metadata:由于 Worker 代码在本地运行,与特定已部署版本关联的版本元数据(如 commit hash、版本标签)不适用或不准确。
-
Analytics Engine:本地开发会话通常不会直接向生产 Analytics Engine 贡献数据。
-
Hyperdrive:正在积极开发中,但目前不受支持。
-
Rate Limiting:本地开发会话通常不应共享或影响已部署 Workers 的速率限制。速率限制逻辑应针对本地模拟进行测试。
虽然 Durable Object 和 Workflow 绑定目前无法设为远程,但你仍可在本地开发期间使用它们,并让它们与远程资源交互。
有两种推荐模式:
-
本地 Durable Objects/Workflows 配合远程绑定:
在 Wrangler 配置 中启用远程绑定时,本地运行的 Durable Objects 和 Workflows 可以访问远程资源。这样,这些绑定虽然在本地运行,但在本地开发期间仍可与远程资源交互。
-
通过 service binding 访问远程 Durable Objects/Workflows:
要与远程 Durable Object 或 Workflow 实例交互,请部署定义这些资源的 Worker。然后,在本地 Worker 中配置指向已部署 Worker 的远程 service binding。 本地 Worker 将能够与远程已部署 Worker 交互,后者再与远程 Durable Objects/Workflows 通信。通过此方法,你可以通过远程 service binding 创建通信通道,在本地开发期间将已部署 Worker 用作远程绑定的代理接口。
-
Cloudflare Access:如果 Worker 受 Cloudflare Access 保护,Wrangler 在连接远程绑定时必须通过 Access 进行身份验证。请参阅 连接到受 Access 保护的 Workers。
-
数据修改:对远程连接绑定的操作(写入、删除、更新)将影响目标 Cloudflare 资源(无论是 preview 还是生产)中的实际数据。
-
计费:通过这些连接与远程 Cloudflare 服务的交互将产生这些服务的标准运营成本(如 KV 操作、R2 存储/操作、AI 请求、D1 使用)。
-
网络延迟:这些远程连接绑定的操作会有网络延迟,因为它们涉及通过互联网通信。
如果你的 Worker 部署在 Cloudflare Access 应用之后——例如,如果账户上的 *.workers.dev 子域受 Access 保护,或者你在 Worker 的自定义路由上设置了 Access 策略——Wrangler 在连接远程绑定时必须通过 Access 进行身份验证。
有两种方式可以对 Access 进行身份验证:
-
交互式登录(本地开发):如果你定义了接受用户登录的策略,Wrangler 会在浏览器中启动交互式
cloudflared access login流程。除了登录正确的账户外,无需额外设置。如果策略仅允许 service token 身份验证,Wrangler 将跳过交互式流程并抛出错误,提示需要 service token 凭据。 -
Service token(CI / 非交互式环境):在 CI/CD 流水线和其他非交互式上下文中,或策略仅允许 service token 身份验证时,Wrangler 无法通过浏览器触发交互式流程。必须通过 Cloudflare Access service token 进行身份验证。如果在非交互式环境中未配置 service token,Wrangler 将抛出错误,而不是尝试交互式流程。
设置 service token 身份验证:
-
创建 service token。
在 Cloudflare 仪表板中,前往 Zero Trust > Access > Service Auth(服务身份验证) > Service Tokens(服务令牌) 并创建新 token。完整参考请参阅 Service tokens。系统会显示 Client ID(客户端 ID) 和 Client Secret(客户端密钥)——请妥善保存,因为 secret 不会再次显示。
-
为保护 Worker 的 Access 应用添加 Service Auth 策略。
打开现有的 Access 应用(已覆盖 Worker 的主机名——通常是
*.<account>.workers.dev的通配符应用,或保护自定义域的应用),并附加新策略:- Action(操作):Service Auth
- Include(包含):你创建的 service token,或 "Any Access Service Token"(如果你希望允许任何 service token 访问 Worker)。
-
向 Wrangler 暴露凭据。
在运行 Wrangler 的环境中设置
CLOUDFLARE_ACCESS_CLIENT_ID和CLOUDFLARE_ACCESS_CLIENT_SECRET系统环境变量:export CLOUDFLARE_ACCESS_CLIENT_ID=<CLIENT_ID> export CLOUDFLARE_ACCESS_CLIENT_SECRET=<CLIENT_SECRET>在 CI 中,将值存储为 secrets,并在运行 Wrangler 的步骤中将其作为环境变量暴露。
Wrangler 提供编程工具,帮助工具作者在通过 Miniflare 运行 Workers 代码时支持远程绑定连接。
主要 API 包括:
startRemoteProxySession:启动允许与远程绑定交互的代理会话。unstable_convertConfigBindingsToStartWorkerBindings:用于转换绑定定义的工具。experimental_maybeStartOrUpdateProxySession:便于启动或更新代理会话的便捷函数。
此函数为给定的一组绑定启动代理会话。它接受控制会话行为的选项,包括带有 Cloudflare 账户 ID 和 API token 的 auth 选项,用于远程绑定访问。
它返回包含以下内容的对象:
readyPromise<void>:会话就绪时 resolve。dispose() => Promise<void>:停止会话。updateBindings(bindings: StartDevWorkerInput['bindings']) => Promise<void>:更新会话绑定。remoteProxyConnectionStringremoteProxyConnectionString:传递给 Miniflare 以进行远程绑定访问的字符串。
unstable_readConfig 工具返回 Unstable_Config 对象,其中包含配置文件中绑定的定义。但这些绑定定义
无法直接用于 startRemoteProxySession。不过,使用 unstable_readConfig 读取绑定声明然后
传递给 startRemoteProxySession 非常方便,因此 wrangler 提供了 unstable_convertConfigBindingsToStartWorkerBindings,这是一个简单的工具,用于将
Unstable_Config 对象中的绑定转换为可传递给 startRemoteProxySession 的结构。
此包装器简化了代理会话管理。它接受:
- 包含以下之一的对象:
- Wrangler 配置文件的路径和潜在的目标环境
- Worker 的名称及其使用的绑定
- 当前代理会话详情(如果没有,此参数可设为
null或不提供)。 - 可能用于远程代理会话的 auth 数据。
它返回已启动或更新的代理会话详情对象,如果不需要代理会话则返回 null。
该函数:
- 根据第一个参数准备代理会话的输入参数。
- 如果没有要使用的远程绑定(也没有预先存在的代理会话),则返回 null,表示不需要代理会话。
- 如果提供了现有代理会话的详情,则相应地更新代理会话。
- 否则启动新的代理会话。
- 返回代理会话详情(之后可作为第二个参数传递给
maybeStartOrUpdateRemoteProxySession)。
以下是将 Miniflare 与 maybeStartOrUpdateRemoteProxySession 配合使用以提供带远程绑定的本地 dev 会话的基本示例。此示例使用单个硬编码的 KV 绑定。
import { Miniflare, MiniflareOptions } from "miniflare";
import { maybeStartOrUpdateRemoteProxySession } from "wrangler";
let mf;
let remoteProxySessionDetails = null;
async function startOrUpdateDevSession() {
remoteProxySessionDetails = await maybeStartOrUpdateRemoteProxySession(
{
bindings: {
MY_KV: {
type: "kv_namespace",
id: "kv-id",
remote: true,
},
},
},
remoteProxySessionDetails,
);
const miniflareOptions = {
scriptPath: "./worker.js",
kvNamespaces: {
MY_KV: {
id: "kv-id",
remoteProxyConnectionString:
remoteProxySessionDetails?.session.remoteProxyConnectionString,
},
},
};
if (!mf) {
mf = new Miniflare(miniflareOptions);
} else {
mf.setOptions(miniflareOptions);
}
}
// ... tool logic that invokes `startOrUpdateDevSession()` ...
// ... once the dev session is no longer needed run
// `remoteProxySessionDetails?.session.dispose()`import { Miniflare, MiniflareOptions } from "miniflare";
import { maybeStartOrUpdateRemoteProxySession } from "wrangler";
let mf: Miniflare | null;
let remoteProxySessionDetails: Awaited<
ReturnType<typeof maybeStartOrUpdateRemoteProxySession>
> | null = null;
async function startOrUpdateDevSession() {
remoteProxySessionDetails = await maybeStartOrUpdateRemoteProxySession(
{
bindings: {
MY_KV: {
type: "kv_namespace",
id: "kv-id",
remote: true,
},
},
},
remoteProxySessionDetails,
);
const miniflareOptions: MiniflareOptions = {
scriptPath: "./worker.js",
kvNamespaces: {
MY_KV: {
id: "kv-id",
remoteProxyConnectionString:
remoteProxySessionDetails?.session.remoteProxyConnectionString,
},
},
};
if (!mf) {
mf = new Miniflare(miniflareOptions);
} else {
mf.setOptions(miniflareOptions);
}
}
// ... tool logic that invokes `startOrUpdateDevSession()` ...
// ... once the dev session is no longer needed run
// `remoteProxySessionDetails?.session.dispose()`与 Miniflare 驱动的本地开发不同,Wrangler 还通过 wrangler dev --remote 提供完全远程的开发模式。远程开发不受 Vite 插件支持。
npx wrangler dev --remoteyarn wrangler dev --remotepnpm wrangler dev --remote在远程开发期间,所有 Worker 代码都会上传到 Cloudflare 基础设施上的临时 preview 环境,保存代码更改时会自动上传。
使用远程开发时,所有绑定自动连接到其远程资源。与本地开发不同,你无法配置绑定使用本地模拟——它们将始终使用 Cloudflare 网络上的已部署资源。
- 对于大多数开发任务,最高效、最有生产力的体验是本地开发,并在需要时使用远程绑定(remote bindings)。
- 你可能希望使用
wrangler dev --remote来测试高度特定于 Cloudflare 网络、无法充分在本地模拟或通过远程绑定测试的特性或行为。
- 由于每次更改都需要上传/部署步骤,迭代速度明显慢于本地开发。
- 使用
--remote标志运行远程开发会话时,每个 zone 强制执行 50 个路由的限制。更多信息请参阅 Workers 平台限制。