长期以来,在 Cloudflare Workers 上运行 Rust 代码,从技术上是可行的——Workers 平台本身支持 WebAssembly,而 Rust 编译到 WebAssembly 是一条相对成熟的路径。
但"技术上可行"和"真正好用"之间,隔着相当大的一段距离。
2021 年 9 月,Cloudflare 发布了 worker crate,把这段距离正式填上了。从那天起,Rust 开发者可以用惯用的 Rust 风格写一个完整的 Worker,不需要懂 JavaScript,不需要手写胶水代码,一行命令创建项目,直接部署到边缘节点。
之前到底哪里不够好
Workers 平台通过 V8 引擎支持 WebAssembly,这意味着任何能编译到 WASM 的语言,理论上都能在上面运行。Rust 对 WebAssembly 的支持是整个语言生态里最成熟的,有 wasm-bindgen、wasm-pack 这些工具链,文档和社区也相对完善。
但问题出在边界处理上。
Workers 的运行环境本质上是一个 JavaScript 环境。fetch()、Request、Response、Headers——这些核心 API 都是 JavaScript 的对象和函数。Rust 代码要调用这些 API,必须经过一个"跳板"(trampoline)步骤:先把 Rust 的数据类型转换成 JavaScript 能理解的形式,调用 JS API,再把结果转回 Rust 类型。
这个过程需要大量的模板代码(boilerplate),而且这些胶水代码的编写,要求开发者对宿主 JavaScript 环境有相当深入的了解。对于一个只想用 Rust 写逻辑的开发者来说,这是一道不必要的认知门槛。
更麻烦的是,就算愿意啃这些胶水代码,现成的 wasm-bindgen 绑定也只覆盖了标准的 Web API,Cloudflare 的私有能力——KV 存储、Durable Objects、环境变量、Secrets——统统没有。开发者要么自己写绑定,要么只能放弃这些功能,用纯 JS 来补。
结果就是:Rust 在 Workers 上能跑,但开发体验远谈不上顺畅,离"原生支持"还差得很远。
worker crate 把这些问题一次性解决了
worker crate 的核心思路是:把所有 JavaScript 边界细节封装在库内部,对外暴露完全符合 Rust 习惯的 API。开发者面对的不是一个"能在 JS 环境里运行的 Rust",而是一个"原生的 Rust 开发体验"。
创建一个新的 Rust Worker 项目只需要一条命令:
wrangler generate --type=rust my-project
之后就是标准的 Rust 开发流程:写代码,用 cargo 管理依赖,用 wrangler 部署。不需要 npm,不需要 webpack,不需要任何 JavaScript 工具链的知识。
一个真实的请求处理器长什么样
下面是官方示例中的一个请求处理器,处理一个带文件上传的 POST 表单请求:
use worker::*;
#[event(fetch)]
pub async fn main(req: Request, env: Env) -> Result<Response> {
// 打印请求方法、路径和地理位置信息
console_log!(
"{} {}, located at: {:?}, within: {}",
req.method().to_string(),
req.path(),
req.cf().coordinates().unwrap_or_default(),
req.cf().region().unwrap_or("unknown region".into())
);
// 只接受 POST 请求
if !matches!(req.method(), Method::Post) {
return Response::error("Method Not Allowed", 405);
}
// 读取表单中的文件字段
if let Some(file) = req.form_data().await?.get("file") {
return match file {
FormEntry::File(buf) => {
Response::ok(&format!("size = {}", buf.bytes().await?.len()))
}
_ => Response::error("`file` part of POST form must be a file", 400),
};
}
Response::error("Bad Request", 400)
}
几个值得关注的细节:
#[event(fetch)] 是一个过程宏,负责把这个 Rust 函数注册为 Worker 的 fetch 事件处理器。背后的 WASM 绑定、事件分发、JS 互操作全部被这个宏处理掉了,对开发者完全透明。
req.cf().coordinates() 和 req.cf().region() 直接返回 Cloudflare 的地理位置信息——这是 Cloudflare 私有的请求元数据,在以前需要手动写 JS 绑定才能访问,现在作为一等公民集成在 API 里。
整段代码的风格是标准的 Rust:模式匹配、? 错误传播、async/await——没有任何 JavaScript 的痕迹,也没有任何 FFI 相关的特殊处理。
worker crate 覆盖了哪些能力
除了基础的 HTTP 请求和响应处理,worker crate 还内置了对以下 Cloudflare 平台能力的封装:
KV 存储:Workers KV 是 Cloudflare 的全球分布式键值存储,在之前的 Rust 方案里完全没有现成的封装,现在可以直接通过 Env 对象访问,API 设计符合 Rust 的惯用风格。
Durable Objects:Cloudflare 的强一致性状态存储,适合需要全局唯一状态的场景。现在也可以在 Rust 里直接定义和使用 Durable Objects。
路由器:内置了一个轻量级的 HTTP 路由框架,支持路径匹配和方法过滤,不需要引入额外的依赖。
环境变量和 Secrets:通过 Env 对象统一访问,类型安全,不需要手动解析 JS 环境。
fetch API:从 Worker 内部发起对外的 HTTP 请求,封装了底层的 JS fetch 调用。
为什么 Rust 是边缘计算的合适选择
Cloudflare 选择 Rust 作为原生支持的第一个非 JS 语言,不是随机的决定。
从技术角度看,Rust 对 WebAssembly 的支持是整个语言生态里最成熟的。wasm-bindgen 解决了 Rust 与 JS 之间的类型桥接问题,web-sys 提供了标准 Web API 的 Rust 绑定,这些都是 worker crate 得以建立的基础。Rust 强大的过程宏系统,让 #[event(fetch)] 这样简洁的 API 设计成为可能,而无需运行时反射或动态分发。
从业务角度看,Cloudflare 内部本身大量使用 Rust。Pingora(代理基础设施)、Saffron(Cron 解析)、Firewall Rules(过滤引擎)都是 Rust 编写的。这意味着 Cloudflare 有足够的 Rust 工程能力来维护和演进这套工具链,而不是把它当成一个实验性项目。
从边缘计算的特殊需求来看,Workers 的执行环境对资源非常敏感:启动时间要快(Cold Start 问题),内存占用要低,执行延迟要可预期。Rust 编译出的 WASM 模块,在这几个维度上都表现良好——没有 GC 停顿,没有运行时开销,WASM 模块体积也相对紧凑。
开发者体验本身是产品竞争力
这次发布背后有一个更值得关注的信号:Cloudflare 把"简化开发者体验"作为一个明确的工程目标,而不只是一句口号。
边缘计算平台之间的技术能力差距正在缩小。在此背景下,谁能让开发者更快上手、更顺畅地把已有代码迁移过来,谁就能在获取开发者心智上占据优势。
对于已经在用 Rust 的工程师来说,之前在 Workers 上写 Rust 的体验,和在原生环境里写 Rust 之间存在明显的摩擦——需要额外学习一套 JS 互操作模式,需要手动处理 Cloudflare 平台能力的绑定,需要维护大量和业务无关的胶水代码。worker crate 把这些摩擦都消除了,让 Rust 开发者可以用已有的习惯和知识直接上手,几乎没有额外的学习成本。
这不只是让 Rust 开发者"多了一个选择",而是让这个选择真正变得实际可用。
小结
worker crate 解决的问题看起来不大:把 Workers 平台 API 封装成 Rust 风格的接口,消除胶水代码。但它代表的是边缘计算平台在语言支持上从"理论可行"到"开发者友好"的一次跨越。
对于已经在用 Rust 的工程师,这是一个直接可用的信号:边缘函数不再是 JavaScript 专属的领地,可以用已有的工具链和习惯,把 Rust 代码直接部署到全球 200 多个 PoP 节点,不需要任何妥协。
项目已完全开源,在 GitHub 和 crates.io 上均可获取。
原文链接:blog.cloudflare.com/workers-rus… 开源仓库:github.com/cloudflare/…