WASM 标准化路线图:GC、组件模型和 WASI 的成熟时间表解读
保持学习,保持输出。WASM 的标准化在加速推进,我在 GitHub 上跟踪了好几个提案仓库,整理了一份可执行的路线图。
但 WASM 的标准化进程很复杂。GC 提案、组件模型(Component Model)、WASI(WebAssembly System Interface),这三个方向各自推进,经常让人搞不清楚"现在到底能不能用"。我用了一个周末把各提案的 Phase 状态梳理了一下,整理出下面的时间线。
一、WASM 标准化提案全景图
WASM 的标准化有一个严格的五阶段流程(Phase 0 → Phase 5)。我先用一个总览图展示关键提案的当前状态:
几个关键节点值得画个重点:
- GC、组件模型和 WASI 的状态应以各自官方仓库为准。 它们的提案阶段、浏览器/运行时支持和工具链成熟度并不总是同步。
- WASI Preview 2 已在官方仓库标注为 stable。 采用前仍需核对目标运行时对所需接口的支持,而不是只依据 Preview 名称判断。
- 组件模型适合用于评估跨语言接口与封装边界。 是否能投入生产,还取决于运行时、绑定生成工具和依赖分发的具体组合。
二、GC 提案:WASM 终于像一门"正经语言"了
GC(垃圾回收)提案对 WASM 的意义,不只是"加了一个垃圾回收器"这么简单。它改变了 WASM 能支持的语言范围。
GC 能减轻部分依赖垃圾回收语言在 WASM 目标上的运行时负担,但实际包体变化取决于编译器、应用代码和目标运行时,应使用项目构建产物测试,而不应预设固定比例。
但对 Rust 开发者来说,GC 的直接影响比较小——Rust 靠所有权系统做内存管理,不需要 GC。反而是 GC 的结构体类型系统对 Rust 和 WASM 的互操作有间接好处:
// GC 提案引入了新的 wasm 类型:struct、array、i31ref
// 这让 WASM 层面的类型更丰富,也方便了跨语言交互
// 例如:Rust 传给 JS 的结构体现在不再必须序列化为字节数组
#[wasm_bindgen]
pub struct User {
pub name: String,
pub age: u32,
}
#[wasm_bindgen]
impl User {
pub fn greet(&self) -> String {
// GC 标准化后,JS 端可以直接持有 User 的引用
// 不需要手动管理生命周期
format!("你好,我是 {},今年 {} 岁", self.name, self.age)
}
}
三、组件模型:WASM 生态的"npm"
如果说 GC 是语言层面的增强,组件模型就是生态层面的革命。它的定位可以简单理解为:WASM 世界的软件包管理器 + ABI 标准。
组件模型的核心价值是跨语言组合。一个 Rust 写的 HTTP 路由器可以调用一个 Python 写的数据分析组件,再调用一个 C 写的加密库——所有这些都编译为 WASM 组件,通过标准接口通信。
// 用 WIT 定义一个组件接口
// 文件: user-service.wit
//
// interface user-service {
// record user {
// name: string,
// age: u32,
// }
//
// get-user: func(id: string) -> option<user>;
// }
// Rust 实现这个接口
use bindings::user_service::{User, get_user};
struct UserServiceImpl;
impl UserServiceImpl {
fn get_user(&self, id: String) -> Option<User> {
// 实际的用户查询逻辑
if id == "001" {
Some(User {
name: "张三".to_string(),
age: 23,
})
} else {
None
}
}
}
// 这个 Rust 组件可以被任何支持 WASM 组件的语言调用
// Python: user = wasm_component.get_user("001")
// JS: const user = await component.getUser("001")
// Go: user, err := component.GetUser("001")
这对选手的利好很明显:你不需要学会所有语言才能做全栈。你可以用 Rust 写核心逻辑(因为你喜欢它的安全性和性能),然后通过组件模型暴露给用其他语言写的上层应用。语言选型从"绑定"变为"选择最合适的那个"。
但组件模型的推进也是最慢的。它不是"标准定好了大家实现就行",而是需要:
- 运行时支持(wasmtime, wasmcloud)
- 工具链支持(
cargo component,wit-bindgen) - 注册表基础设施(类似 npm registry)
- 社区接受度(这可能是最难的部分)
四、WASI 的发展:从"文件系统访问"到"完整操作系统抽象"
WASI 是 WebAssembly 脱离浏览器、走向服务器端/边缘计算的关键基础设施:
WASI Preview 2 是这个路线图中的一个关键里程碑。它在 Preview 1 的基础上补了几个大坑:
- 支持异步 I/O(通过
wasi:io/poll接口) - 标准化了 HTTP 支持(
wasi:http——不需要每个语言自己实现 HTTP 客户端了) - 引入了组件模型作为接口定义标准
参考资料
// 使用 WASI Preview 2 的 HTTP 接口(通过 wit-bindgen 生成绑定)
// 这个代码运行在 WASM 沙箱中,直接使用 WASI 提供的 HTTP 能力
use wasi::http::outgoing_handler;
use wasi::http::types::{self, Method, Scheme};
fn make_request(url: &str) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
// 解析请求目标 URL
let headers = types::new_fields(&[
("User-Agent".to_string(), "WASI-HTTP/0.1".as_bytes().to_vec()),
("Accept".to_string(), "application/json".as_bytes().to_vec()),
]);
let request = types::new_outgoing_request(
&Method::Get,
None, // 不指定路径参数
Some(&Scheme::Https), // HTTPS 协议
"api.github.com".to_string(), // 目标主机
Some("/users/octocat".to_string()), // URL 路径
Some(&headers),
)?;
// 发送 HTTP 请求(通过 WASI 提供的系统级支持)
let response = outgoing_handler::handle(request, None)?;
// 读取响应体
let body = response.body();
let mut buffer = Vec::new();
// 从 WASI 流中读取数据
body.read_to_end(&mut buffer)?;
Ok(buffer)
}
以前要在 WASM 里发 HTTP 请求,需要把 JavaScript 的 fetch 包装成 wasm-bindgen 的导出函数。WASI 把这个能力原生化了——不需要 JavaScript 中间层。这对 Serverless/边缘计算平台(如 Cloudflare Workers、Fastly Compute@Edge)来说是重大利好。
五、总结
梳理完 WASM 标准化的路线图,我有几点核心判断:
GC 提案标准化是"多语言 WASM"的起点。之前只有 Rust/C/C++ 能高效产出 WASM,现在 Java/Kotlin/Dart 都加入了。WASM 不再是"系统语言的专属编译目标"。
组件模型是生态成型的关键变量。如果它能像 npm 之于 Node.js 那样建立生态,WASM 就能从"编译目标"变成"完整的软件分发平台"。但这个目标至少需要 2-3 年才能在生产中广泛使用。
WASI Preview 2 是服务器端 WASM 的里程碑。异步 I/O + 原生 HTTP 让 WASM 在 Serverless 场景下不再受限于 JavaScript 桥接的性能开销。
对选手来说:现在学 WASM 不算早。虽然很多提案还没完全稳定,但 Rust → WASM → 浏览器/Serverless 这条技术链已经在生产环境中运行(Cloudflare Workers 每天处理亿万级请求)。现在入局,一两年后提案稳定时你已经是有经验的开发者了。
保持学习,保持输出。WASM 是我的长期研究方向之一,下周计划写一个 Rust + 组件模型的实际案例,看看它到底好不好用。

430

被折叠的 条评论
为什么被折叠?



