1. 从标题到落地:cloudflare-os 到底是个什么东西
第一次看到cloudflare-os这个标题,我脑子里蹦出来的第一个念头是:这名字起得有点大。OS 这个词在计算机领域是有分量的,它意味着资源调度、进程管理、系统调用这一整套底层逻辑。但结合热搜词里的 Cloudflare Workers、wrangler、pnpm 这几个关键词,我基本能判断出来,这里的 "OS" 不是传统意义上的操作系统,而是一种面向边缘计算场景的运行时编排思路——把 Cloudflare 的全球边缘网络当成一台虚拟的分布式计算机来用,而 Workers 就是这台机器上的"进程"。
说白了,cloudflare-os这个项目要解决的核心问题是:如何把散落在全球数百个边缘节点上的计算能力,组织成一个对开发者友好的、可编程的统一运行时环境。传统做法里,你要部署一个全球可用的服务,得考虑区域选择、负载均衡、数据同步、冷启动优化这一堆破事。而 Cloudflare Workers 的模型是,你写一段 JavaScript 或 TypeScript,wrangler 一推,它自动跑在全球几百个节点上,用户请求就近处理,延迟压到个位数毫秒。cloudflare-os想做的,就是在这个基础之上再抽象一层,让开发者像调用本地系统 API 一样去调用边缘能力。
这个项目适合谁来参考?我梳理了一下,大概三类人最值得花时间研究。第一类是全栈开发者,尤其是那些已经在用 Next.js、Remix、Astro 这类框架做 SSR 的人,他们天然需要边缘运行时来降低 TTFB。第二类是AI 应用开发者,热搜词里 AI、AI Agent、AI 大模型这些词反复出现,说明这个项目和 AI 工作流的结合是个热点——把推理请求分发到边缘,用 Workers AI 做轻量级模型调用,再用 Durable Objects 管理会话状态,这套组合拳打下来,AI 应用的响应速度和成本结构都会有质的变化。第三类是基础设施工程师,他们关心的是如何用代码定义边缘拓扑,如何做灰度发布,如何观测全球节点的运行状态。
我个人的判断是,cloudflare-os这个概念的价值不在于它真的实现了一个完整的操作系统,而在于它提供了一种思维框架:把边缘网络当成一台计算机来编程。这个视角一旦建立起来,很多以前觉得麻烦的事情——比如全球状态同步、边缘缓存失效、跨区域事务——都会找到新的解法。接下来我会从设计思路、核心细节、实操过程、问题排查四个维度,把这个项目拆开揉碎讲清楚。
2. 整体设计思路:为什么是 Workers 而不是容器
2.1 边缘运行时的选型逻辑
要理解cloudflare-os的设计,得先搞清楚一个根本问题:为什么它选择 Workers 作为底层运行时,而不是把 Docker 容器搬到边缘去跑?这个选择背后有一整套工程权衡。
容器方案的优势是生态成熟,你现有的 Node.js 应用、Python 服务、Go 二进制,打个镜像就能跑。但容器在边缘场景下有个致命伤:冷启动。一个典型的 Node.js 容器冷启动要几百毫秒到几秒,而边缘计算的卖点就是低延迟,用户请求从东京打到法兰克福,网络往返才 100 多毫秒,结果你冷启动花了 800 毫秒,这体验就崩了。Workers 用的是 V8 Isolate 技术,启动时间在 5 毫秒以内,几乎可以认为是常驻内存的。这个数量级的差异,决定了边缘场景下 Isolate 模型比容器模型更合适。
另一个关键考量是安全隔离。V8 Isolate 之间的隔离是语言级别的,比容器依赖的 namespace 和 cgroup 更轻量,但安全性并不差。Cloudflare 在全球节点上跑着数百万个 Worker,如果隔离机制有漏洞,早就出大事了。这套模型经过大规模生产验证,可靠性是有保障的。
注意:Workers 运行时不是完整的 Node.js,它基于 Web 标准 API 构建,没有
fs、net这些 Node 核心模块。如果你要把现有 Node 应用迁过来,得先确认依赖树里有没有这些模块,否则 wrangler 构建阶段就会报错。
2.2 从"部署单元"到"操作系统"的抽象跃迁
cloudflare-os这个名字里的 "OS" 体现在哪里?我的理解是,它把原本分散的基础设施能力——KV 存储、Durable Objects、R2 对象存储、Queues 消息队列、AI 推理——统一到了一套编程模型下。这就像操作系统把磁盘、内存、网络设备抽象成文件描述符和系统调用一样。
具体来说,这套抽象包含几个层次。最底层是计算层,由 Workers 提供无服务器函数执行环境。往上是状态层,Durable Objects 提供强一致的单点状态,KV 提供最终一致的全局键值存储,R2 提供兼容 S3 的对象存储。再往上是协调层,Queues 做异步任务分发,Workflows 做长时间运行的编排。最顶层是智能层,Workers AI 提供边缘推理能力,Vectorize 提供向量检索。
这套分层设计的精妙之处在于,每一层都有明确的一致性模型和延迟特征,开发者可以根据业务需求选择合适的状态原语。比如用户会话状态用 Durable Objects,因为需要强一致;商品目录缓存用 KV,因为可以容忍短暂的不一致换取更低的读取延迟;用户上传的图片用 R2,因为对象存储成本低且容量无限。
2.3 工具链设计:wrangler 与 pnpm 的配合
热搜词里出现了 pnpm 和 wrangler,这两个工具在cloudflare-os的工作流里扮演着不同但互补的角色。wrangler 是 Cloudflare 官方的 CLI,负责本地开发、构建、部署、日志查看这一整套生命周期管理。pnpm 则是包管理器,负责依赖安装和 monorepo 管理。
为什么是 pnpm 而不是 npm 或 yarn?这里有个很实际的考量。边缘项目的依赖树往往比较深,尤其是当你引入大量 Workers 生态的库时。pnpm 用硬链接和内容寻址存储,磁盘占用比 npm 少 50% 以上,安装速度快 2 到 3 倍。更重要的是,pnpm 的严格依赖隔离机制能避免"幽灵依赖"问题——就是你的代码引用了没有在 package.json 里声明的包,本地能跑但部署到边缘就挂。在边缘场景下,这种问题排查起来特别痛苦,因为你看不到完整的文件系统。
wrangler 的配置文件wrangler.toml是整个项目的核心,它定义了 Worker 的名称、入口文件、兼容性日期、环境变量、绑定关系。我见过太多人在这里踩坑,比如忘了设置compatibility_date,导致运行时行为和你本地测试的不一致。这个字段决定了 Workers 运行时采用哪个时间点的 API 行为,必须显式指定,不能依赖默认值。
3. 核心细节解析:绑定、路由与状态管理
3.1 绑定机制:Worker 如何"看见"外部资源
在cloudflare-os的编程模型里,Worker 访问外部资源不是通过 IP 地址和端口,而是通过绑定。这个概念有点像操作系统的设备文件——你不需要知道磁盘的物理地址,只需要打开/dev/sda就能读写。绑定在wrangler.toml里声明,运行时通过环境变量注入到 Worker 代码中。
举个例子,你要用一个 KV 命名空间来存配置:
# wrangler.toml name = "cloudflare-os-demo" main = "src/index.ts" compatibility_date = "2024-09-23" [[kv_namespaces]] binding = "CONFIG_STORE" id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"然后在代码里这样访问:
export default { async fetch(request: Request, env: Env): Promise<Response> { const config = await env.CONFIG_STORE.get("feature_flags"); return new Response(config ?? "{}", { headers: { "content-type": "application/json" } }); } };这种设计的好处是依赖显式化。你打开 wrangler.toml 就能看到这个 Worker 依赖哪些资源,不需要去翻代码找数据库连接字符串。而且绑定是类型安全的,如果你用 TypeScript,wrangler 会自动生成Env接口的类型定义,写错绑定名编译期就会报错。
实操心得:绑定名称建议用大写下划线风格,和普通环境变量区分开。我见过有人把 KV 绑定命名为
config,结果和process.env.config混淆,调试了半天才发现是绑定没生效。
3.2 路由策略:请求如何找到正确的 Worker
cloudflare-os的路由层设计有几个关键决策点。最基础的是自定义域名和workers.dev 子域名的选择。workers.dev 适合开发和测试,零配置,推上去就能用。但生产环境一定要绑自定义域名,原因有三:一是 SEO 和品牌一致性,二是可以配置更细粒度的缓存规则,三是避免 workers.dev 域名在某些网络环境下被限速。
路由匹配的优先级规则也容易踩坑。Cloudflare 的规则是:精确路径 > 通配符路径 > 兜底路由。比如你同时定义了/api/users和/api/*,请求/api/users会命中第一个。这个规则看起来简单,但在多 Worker 协作的场景下,路由冲突会导致请求被错误的 Worker 处理。我的建议是,在项目初期就把路由规划写进文档,用表格管理起来。
| 路由模式 | 优先级 | 适用场景 | 注意事项 |
|---|---|---|---|
/api/v1/users | 最高 | 精确 API 端点 | 路径变更需同步更新客户端 |
/api/v1/* | 中 | API 版本通配 | 注意与精确路径的覆盖关系 |
/assets/* | 中 | 静态资源 | 配合 Cache API 使用 |
* | 最低 | SPA 兜底 | 返回 index.html |
3.3 状态管理:Durable Objects 的正确打开方式
Durable Objects 是cloudflare-os里最容易被误用的组件。它的核心特性是单点强一致——每个 Durable Object 实例在全球只有一个,所有请求都路由到同一个实例上。这听起来像是回到了单机时代,但实际上是解决分布式状态问题的巧妙方案。
什么时候该用 Durable Objects?我的判断标准是:需要串行化访问的、有状态的、低延迟的协调场景。比如实时协作编辑的文档锁、游戏房间的状态机、AI 对话的会话上下文。这些场景的共同点是,如果状态分散在多个节点上,一致性维护的成本远高于把请求集中到一个点。
但 Durable Objects 不是银弹。它的吞吐量受限于单个实例的处理能力,官方建议单个 DO 的 QPS 控制在 1000 以内。如果你的场景是读多写少,用 KV 加缓存更合适;如果是纯写入的日志流,用 Queues 或 R2 更经济。我见过一个项目把所有用户状态都塞进一个 Durable Object,结果上线当天就撞到了性能天花板,后来拆成按用户 ID 分片的多个 DO 才解决。
// 按用户 ID 分片的 Durable Object 用法 const id = env.USER_SESSION.idFromName(userId); const stub = env.USER_SESSION.get(id); return stub.fetch(request);这段代码的关键是idFromName,它根据用户 ID 生成一个确定性的 Object ID,保证同一个用户总是路由到同一个 DO 实例。分片策略的选择直接影响系统的扩展性,用用户 ID 分片适合会话场景,用地理区域分片适合位置服务,用时间窗口分片适合时序数据处理。
4. 实操过程:从零搭建一个边缘 AI 网关
4.1 环境准备与项目初始化
先把基础环境搭起来。Node.js 版本建议用 20 LTS 或更高,wrangler 对 Node 版本有要求,太老的版本会在安装阶段就报错。pnpm 的安装方式取决于你的操作系统,macOS 和 Linux 下用 corepack 是最省事的:
corepack enable corepack prepare pnpm@latest --activateWindows 用户如果遇到 pnpm 安装失败,大概率是权限问题或者网络问题。权限问题用管理员身份运行终端可以解决,网络问题可以配置国内镜像源。这里不展开讲网络配置,只说一个原则:pnpm 的 registry 配置在.npmrc文件里,项目级配置优先于全局配置。
初始化项目:
pnpm create cloudflare@latest cloudflare-os-demo cd cloudflare-os-demo pnpm install这个命令会生成一个标准的 Workers 项目骨架,包含src/index.ts、wrangler.toml、package.json和tsconfig.json。我建议在package.json里加几个脚本,方便日常开发:
{ "scripts": { "dev": "wrangler dev", "deploy": "wrangler deploy", "tail": "wrangler tail", "typecheck": "tsc --noEmit" } }wrangler dev启动本地开发服务器,默认监听 8787 端口。它有两种模式:本地模式和远程模式。本地模式在 Node.js 里模拟 Workers 运行时,速度快但和真实环境有差异;远程模式把代码推到边缘节点执行,真实但每次改动都要上传。我的习惯是日常开发用本地模式,联调测试用远程模式。
4.2 配置 AI 绑定与推理端点
cloudflare-os和 AI 的结合是这个项目最有想象力的部分。Workers AI 提供了在边缘节点直接运行推理的能力,不需要把请求转发到中心化的推理集群。配置方式是在 wrangler.toml 里声明 AI 绑定:
[ai] binding = "AI"然后在代码里调用:
export default { async fetch(request: Request, env: Env): Promise<Response> { const { prompt } = await request.json(); const response = await env.AI.run("@cf/meta/llama-3-8b-instruct", { prompt, max_tokens: 512, temperature: 0.7 }); return Response.json({ result: response.response }); } };这段代码看起来简单,但有几个参数需要仔细调。max_tokens控制生成的最大长度,设太大浪费计算资源,设太小回答会被截断。temperature控制随机性,0 到 0.3 适合事实性问答,0.7 到 1.0 适合创意写作。我实测下来,对于客服场景,temperature 设 0.3 左右最稳,回答既不会太死板也不会胡言乱语。
注意:Workers AI 的模型列表会更新,
@cf/meta/llama-3-8b-instruct这个模型名可能随时间变化。部署前先用wrangler ai models命令查一下当前可用的模型列表,避免用了一个已经下线的模型。
4.3 用 Durable Objects 管理对话上下文
AI 对话的核心难点是上下文管理。每次请求都要把历史对话带上,否则模型不知道之前聊了什么。但历史对话不能无限增长,否则 token 消耗会爆炸。我的方案是用 Durable Object 存会话历史,每次请求时做滑动窗口截断。
export class ChatSession { state: DurableObjectState; history: Array<{ role: string; content: string }> = []; constructor(state: DurableObjectState) { this.state = state; this.state.blockConcurrencyWhile(async () => { this.history = (await this.state.storage.get("history")) ?? []; }); } async fetch(request: Request) { const { message } = await request.json(); this.history.push({ role: "user", content: message }); // 滑动窗口:只保留最近 10 轮对话 if (this.history.length > 20) { this.history = this.history.slice(-20); } const response = await this.env.AI.run("@cf/meta/llama-3-8b-instruct", { messages: this.history, max_tokens: 512 }); this.history.push({ role: "assistant", content: response.response }); await this.state.storage.put("history", this.history); return Response.json({ reply: response.response }); } }这里有个细节值得展开:blockConcurrencyWhile保证在构造函数完成之前,不会有其他请求进来。这是 Durable Objects 的并发控制机制,避免多个请求同时读写history导致数据竞争。如果你不熟悉这个概念,可以把它理解成数据库事务的串行化隔离级别。
滑动窗口的大小需要根据模型上下文长度和成本预算来定。Llama 3 8B 的上下文窗口是 8K token,一轮对话大概消耗 100 到 300 token,所以理论上可以保留 20 到 30 轮。但考虑到成本,我建议保留 10 轮左右,更早的历史可以做摘要压缩,把关键信息提取出来存成一条 system message。
4.4 部署与灰度发布
部署命令很简单:
pnpm deploy但生产环境的部署不能这么随意。cloudflare-os的部署策略我推荐用版本化部署加流量切分。wrangler 支持--env参数来管理多环境配置:
[env.staging] name = "cloudflare-os-staging" vars = { ENVIRONMENT = "staging" } [env.production] name = "cloudflare-os-production" vars = { ENVIRONMENT = "production" }部署到 staging:
pnpm wrangler deploy --env staging验证没问题后再推 production。如果要做灰度,可以用 Cloudflare 的 Load Balancer 或者 Workers 的gradual_deployments配置,把 5% 的流量先切到新版本,观察错误率和延迟指标,确认稳定后再逐步扩大比例。
实操心得:部署后一定要用
wrangler tail看实时日志。我遇到过好几次本地测试正常、部署后报错的情况,原因五花八门——有的是环境变量没配,有的是绑定 ID 写错了,有的是兼容性日期设得太新导致某个 API 行为变了。tail 是排查这类问题的第一手段。
5. 常见问题与排查技巧实录
5.1 pnpm 安装失败与依赖问题
pnpm 安装失败是高频问题,我整理了几种典型情况和对应的排查思路。第一种是ERR_PNPM_NO_MATCHING_VERSION,说明你指定的版本号在 registry 里不存在,检查一下 package.json 里的版本约束是不是写错了。第二种是ERR_PNPM_PEER_DEP_ISSUES,这是 peer dependency 冲突,用pnpm why <package>可以追溯是哪个包引入的冲突。
Ubuntu 下安装 pnpm 有个常见坑:用npm install -g pnpm装完后,pnpm命令找不到。这是因为 npm 全局 bin 目录不在 PATH 里。解决办法是export PATH="$PATH:$(npm config get prefix)/bin",写进.bashrc或.zshrc里持久化。
删除 pnpm 也要注意,npm uninstall -g pnpm只删了包,缓存目录还在~/.local/share/pnpm或~/.pnpm-store。彻底清理需要手动删这两个目录,否则重装后可能因为缓存损坏继续报错。
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
ERR_PNPM_NO_MATCHING_VERSION | 版本号不存在 | 检查 package.json 版本约束 |
ERR_PNPM_PEER_DEP_ISSUES | peer 依赖冲突 | pnpm why追溯来源 |
| 命令找不到 | PATH 未配置 | 添加 npm prefix/bin 到 PATH |
| 安装卡住 | registry 不可达 | 检查网络和 registry 配置 |
| 缓存损坏 | 上次安装中断 | 删除 pnpm-store 重新安装 |
5.2 Workers 运行时兼容性问题
Workers 运行时和 Node.js 的差异是新手最容易踩的坑。最常见的报错是Cannot find module 'fs'或Cannot find module 'crypto'。前者说明你依赖了 Node 的文件系统 API,边缘环境没有文件系统,必须换方案——配置读 KV,文件读写用 R2。后者说明你用了 Node 的 crypto 模块,应该换成 Web Crypto API。
// 错误:Node.js 写法 import crypto from "crypto"; const hash = crypto.createHash("sha256").update(data).digest("hex"); // 正确:Web Crypto 写法 const hashBuffer = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(data)); const hash = [...new Uint8Array(hashBuffer)].map(b => b.toString(16).padStart(2, "0")).join("");另一个高频问题是compatibility_date设置不当。这个日期决定了 Workers 运行时采用哪个版本的 API 行为。设得太早,新 API 用不了;设得太晚,某些行为可能和你的代码预期不符。我的建议是设成项目启动当天的日期,然后在升级时逐步调整,每次只改一个版本,观察有没有回归。
5.3 AI 推理的超时与限流处理
Workers AI 的推理请求有超时限制,默认是 30 秒。对于长文本生成,这个时间可能不够。解决方案是流式响应,把生成结果分块返回,而不是等全部生成完再返回。
const stream = await env.AI.run("@cf/meta/llama-3-8b-instruct", { prompt, stream: true }); return new Response(stream, { headers: { "content-type": "text/event-stream" } });流式响应不仅解决了超时问题,还改善了用户体验——用户可以边看边等,感知延迟大幅降低。但要注意,流式响应的错误处理更复杂,如果生成中途出错,已经发送的部分无法撤回,需要在客户端做容错。
限流方面,Workers AI 有每秒请求数限制,具体数值取决于你的账户等级。如果触发限流,会返回 429 状态码。处理策略是加指数退避重试:
async function callAIWithRetry(env, prompt, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { return await env.AI.run("@cf/meta/llama-3-8b-instruct", { prompt }); } catch (e) { if (e.status === 429 && i < maxRetries - 1) { await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000)); continue; } throw e; } } }5.4 调试技巧与可观测性建设
边缘环境的调试比本地环境麻烦,因为你看不到完整的运行时状态。我的经验是日志要打够,但不要打太多。console.log在 Workers 里会被 wrangler tail 捕获,但每条日志都有成本,高频日志会拖慢执行速度。
结构化日志比纯文本日志好用得多:
console.log(JSON.stringify({ level: "info", event: "ai_request", model: "llama-3-8b", prompt_length: prompt.length, timestamp: Date.now() }));这样在 tail 输出里可以用 jq 过滤,比如wrangler tail --format json | jq 'select(.event == "ai_request")'。对于生产环境,建议接入 Analytics Engine,把关键指标写进去,然后在 Cloudflare Dashboard 里做可视化。
避坑技巧:wrangler tail 默认只显示最近几分钟的日志,如果你要排查历史问题,得用
--since参数指定时间范围。另外,tail 会消耗你的 Workers 请求配额,长时间挂着 tail 可能产生额外费用,排查完记得关掉。
6. 性能优化与成本控制的实战经验
6.1 冷启动与预热策略
虽然 Workers 的冷启动已经很快了,但在极端情况下——比如某个边缘节点长时间没有请求——还是会有几十毫秒的额外延迟。对于延迟敏感的应用,可以用 Cron Triggers 做定时预热:
[triggers] crons = ["*/5 * * * *"]export default { async scheduled(event: ScheduledEvent, env: Env) { // 预热关键路径 await env.KV.get("warmup_key"); await env.AI.run("@cf/meta/llama-3-8b-instruct", { prompt: "ping", max_tokens: 1 }); } };每 5 分钟触发一次,保持关键资源的热度。这个策略的成本很低,Cron Triggers 的免费额度足够覆盖大多数场景。
6.2 缓存策略的分层设计
cloudflare-os的缓存体系有三层:边缘缓存、KV 缓存、Durable Object 内存缓存。边缘缓存用 Cache API,适合静态资源和幂等的 API 响应;KV 缓存适合配置和低频变更的数据;DO 内存缓存适合会话内的频繁读取。
// 三层缓存示例 async function getData(key: string, env: Env) { // 第一层:边缘缓存 const cache = caches.default; const cached = await cache.match(key); if (cached) return cached; // 第二层:KV const kvData = await env.KV.get(key); if (kvData) { const response = new Response(kvData); await cache.put(key, response.clone()); return response; } // 第三层:回源 const fresh = await fetchFromOrigin(key); await env.KV.put(key, fresh, { expirationTtl: 3600 }); return fresh; }缓存失效是另一个难点。边缘缓存没有主动失效机制,只能靠 TTL 过期。如果数据变更需要立即生效,得用版本化 key 或者 Cache Tags。我的经验是,对于大多数场景,TTL 设 60 到 300 秒就够了,用户对几分钟的数据延迟通常不敏感。
6.3 成本结构与优化方向
Workers 的计费模型是按请求数和 CPU 时间。请求数好理解,每次 fetch 算一次。CPU 时间是实际执行代码消耗的时间,不包括等待 IO 的时间。这个模型对 IO 密集型的应用很友好,因为等待网络响应的时间不计费。
优化成本的核心思路是减少请求数和降低 CPU 时间。减少请求数可以用缓存、合并 API、批量处理。降低 CPU 时间要避免在 Worker 里做重计算,把复杂逻辑放到 Durable Objects 或者外部服务。
| 优化方向 | 具体手段 | 预期效果 |
|---|---|---|
| 减少请求数 | 边缘缓存、API 合并 | 请求成本降 30-70% |
| 降低 CPU | 避免重计算、用流式处理 | CPU 成本降 20-50% |
| 存储优化 | KV 替代 DO、R2 生命周期 | 存储成本降 40-60% |
| AI 优化 | 小模型优先、结果缓存 | 推理成本降 50-80% |
AI 推理的成本优化空间最大。同样的 prompt,用 8B 模型和 70B 模型的成本差好几倍。我的策略是分级路由:简单问题用 8B 模型,复杂问题才升级到 70B。判断复杂度可以用关键词匹配或者一个小型分类模型,准确率做到 80% 以上就能省下大量成本。
7. 这个项目后续还能怎么扩展
cloudflare-os的框架搭起来之后,扩展方向其实很多。我目前比较看好的几个方向,一个是多 AI 协作,用 Queues 把任务分发给不同的模型,各自处理擅长的部分,最后汇总结果。比如一个负责检索,一个负责推理,一个负责格式化输出。另一个方向是边缘 RAG,用 Vectorize 存向量,Workers AI 做 embedding,把检索增强生成整套流程都放在边缘完成,延迟可以压到 100 毫秒以内。
还有一个我觉得很有意思的扩展是AI Agent 的容错控制。Agent 在执行任务时可能会调用外部工具,工具调用失败是常态。用 Durable Objects 记录 Agent 的状态机,每一步都有检查点和回滚逻辑,失败时自动重试或者降级。这套机制在中心化环境里实现起来很重,但在边缘环境下,因为状态和计算都在同一个节点,实现起来反而更自然。
最后分享一个小技巧:wrangler dev的--remote模式支持热重载,改完代码保存后自动重新部署到边缘,开发体验和本地开发几乎一样。但要注意,remote 模式下的日志输出有延迟,调试时不要依赖日志的实时性,关键路径还是用本地模式验证。