Fullstack in Rust 无痛且无不必要的抽象
那种熟悉的感觉:你想要用 Rust 写一个小 Web 应用,但搭建基础设施的时间比写实际逻辑还长。首先你要选一个 Web 框架(Axum 或 Actix-web),然后选一个模板引擎(Askama 或 Tera),再想办法把数据传给前端,而不会让你的代码变成无尽的 API 端点描述。最终,一个只有 10 行逻辑的项目变成了几百行配置。
Tokio 开发团队(没错,就是为 Rust 生态一半项目编写异步运行时的那个团队)决定解决这个问题。他们推出了 Topcoat——一个框架,旨在让 Rust 开发像 Ruby on Rails 或 Next.js 一样快速愉快,同时保留类型安全的所有好处。
它到底是什么
Topcoat 是一个遵循"batteries included"原则的模块化全栈框架。它不强迫你在服务端渲染(SSR)和客户端响应式之间做选择,而是提供了一种混合方式:你用 Rust 编写代码,框架自己决定什么应该在服务器上运行,什么应该转换成 JavaScript 在浏览器中执行。
该项目目前处于早期阶段(实验状态),API 可能会发生变化。但对于那些厌倦了技术动物园的人来说,其内置的架构理念看起来非常可靠。
无痛苦、无 WASM 包的响应式
通常,如果你想让页面上的一个按钮变得生动,你有两条路:要么用 JS/TS 编写,要么引入沉重的 WebAssembly。Topcoat 提供了第三条路。
在 view! 宏内部,特殊的表达式 $(...) 是常规的 Rust 代码。它会经过编译器检查,但 Topcoat 知道如何将其翻译成 JavaScript。当你编写一个改变状态的点击处理器(signal)时,你不需要设置前端构建或描述 API。框架本身就会让它在浏览器中即时工作。
如果更新需要从服务器获取数据(例如数据库搜索),"shards"就来救场了。你用 #[shard] 属性标记一个组件,当参数变化时,Topcoat 会自动在服务器上重新渲染它,然后小心翼翼地在浏览器中替换 HTML 片段。
让一切井然有序的路由
Topcoat 没有建议在一个巨大的 main.rs 文件中描述路径树,而是建议使用文件夹结构。如果你用过 Next.js,你会感到宾至如归。
一个 src/app/about.rs 文件会自动在 /about 可用,而 src/app/posts/id.rs 会变成带有 /posts/{post_id} 参数的路由。这里没有运行时魔法——这是一个可选功能,如果你喜欢这种秩序感,可以启用它。
保持 HTML 本色的模板
Rust 中的许多模板引擎要么离 HTML 太远,要么强迫你写大量额外代码。Topcoat 中的 view! 宏尽可能接近标记语言,同时仍然允许你使用常规 Rust 构造,如循环 for 和条件 if。
顺便说一句,对于那些关心代码整洁性的人:这个包包含了一个 CLI 工具 topcoat fmt,它甚至可以格式化宏内部的代码。这是一个在其他项目中经常缺失的小功能。
现成的组件和资源
开发者们走了 shadcn/ui 的路线。你不是把一个笨重的组件库作为依赖引入,而是使用 topcoat ui 命令。它会把你需要(按钮、卡片、表单)的组件代码直接复制到你的项目中。这让你可以随意更改设计,而不必与库样式搏斗。一切都基于 Tailwind CSS 构建,直接集成到构建流程中。
图片和字体的处理也简化了:
框架会为文件名添加哈希以实现缓存,并确保资源可用。
现在值得尝试吗
Topcoat 看起来是 Rust 中"正确"的 Web 框架的一次尝试,类型系统在这里有所帮助而不是妨碍开发速度。
它绝对适合这些人:
- 想要用 Rust 快速构建原型或内部工具的人。
- 厌倦了后端和前端之间鸿沟的开发者。
- 重视 Tokio 生态并信任其架构决策的人。
该项目目前正在积极增长。作者计划添加 WebSocket 支持、后台任务,甚至 OpenAPI 规范生成。如果你一直在寻找用 Rust 写 Web 应用的理由,那么 Topcoat 的出现可能就是那个信号。
去看看 tokio-rs/topcoat 仓库——那里有一份很棒的入门指南。但请记住:该项目是实验性的,因此在关键任务系统中使用它还为时过早。
相关项目