两个月前,朱利安(Julien)与卡尔·勒歇(Carl Lerche)发布托普科特(Topcoat),一个含视图、组件、邮件与吐司(Toasty)的全栈Rust框架,旨在让Rust网页开发效率媲美其他语言,团队正推出新特性。卡尔·勒歇的职业始于用红宝石轨道(Ruby on Rails)构建网页应用,当时15分钟建博客视频具开创性,写软件曾充斥样板。红宝石轨道证明高效且有趣,他爱上它并加入核心团队数年,仍是历史前50贡献者,其哲学影响深远。
正文
两个月前,我们(Julien 和我)发布了 Topcoat,一个开箱即用的 Rust 全栈框架,包含视图、组件、邮件发送、ORM(Toasty)等。Topcoat 目标是让 Rust 写 Web 应用和其他语言一样高效。我们一直在加紧开发功能,现在聊聊新进展。
作者从 Ruby on Rails 开启职业开发生涯。当时“15 分钟写博客”视频具有开创性,写软件原本繁琐,Rails 证明了开发可以高效且有趣。Rails 哲学对软件开发整体的影响难以高估。
之后约 13 年,我着手构建 Rust 网络生态,始终瞄准高层应用开发,想用 Rust 捕捉 Rails 的魔力,做出运行极快、内存仅需约 20MB 的应用。
Rust 虽不如某些现代语言优雅,但高层应用极少用到生命周期和泛型,表现力足够,搭配设计良好的库写出的应用也很美观。
Rust 是 AI 驱动开发新时代最佳的通用语言,适用于 Web 或服务端应用。库与框架角色在演变,但良好约定和抽象能帮 LLM 更快、更少错误地工作,这正是推动 Rust 开箱即用框架的原因。
我与 Julien 合作,他主导 Topcoat 前端设计,我专注 Toasty 和数据库层。框架具体形态仍在探索,但已初具雏形。
Topcoat 和 Toasty 有什么新进展?
Topcoat 0.9 及更高版本的客户端响应式
今天我们发布了 Topcoat v0.9。做 Web 框架通常先选浏览器端或服务器端渲染。服务端渲染对多数应用是最好的默认,但我们需要在必要时能降到完全交互、零延迟的 UI。
在服务器端跟踪客户端信号
Topcoat 起步时用了 signals 和 view! 宏内特殊的运行时表达式语法:一套类型安全的 Rust 子集,可转译到 JavaScript 在浏览器重跑。思路是把多数渲染和业务逻辑放服务端,只点缀运行时表达式弥补延迟,比如显示加载动画。用 signal 初始化状态变量活在浏览器,点击按钮修改信号,计数更新无需服务器往返。
但仅靠运行时表达式无法修改标记结构本身。为此加入 shards,一种参数变化时在服务端重渲染的特殊组件。当 query 信号变化,浏览器把当前值发给服务端,重跑 shard 并返回更新 HTML。
在 Topcoat 0.8 中,响应信号变化更简单:可在服务端渲染 UI 时直接读取信号。因为结果依赖信号值,Topcoat 只会重新获取跟踪该信号值的页面部分。更新 HTML 元素时用 morph 避免丢失焦点或输入状态,甚至整页可因信号变更重渲染。
从服务器流式推送 UI 变更
响应客户端状态变更很棒,但若要因服务端状态变更更新 UI,Topcoat 提供 live! 和 emit! 宏。live! 视图能发出无限次 UI 更新。
简单例子是流式 SSR 或悬念:尽快渲染加载骨架,数据就绪后替换真实内容。Topcoat 自带 suspense 和 error_boundary 组件,类似 React。也可用 live! 先 emit! 加载提示,加载数据后 emit! 正式内容。
高级用例是多次 emit! 更新进度百分比。
从 0.9 起,Topcoat 支持服务端推送:浏览器与服务器建 WebSocket 长连,订阅 UI 变更。比如聊天界面,live! 视图订阅聊天变化,初始加载渲染一次,之后等待变更循环重渲。
Toasty,Topcoat 的数据库客户端
Toasty 数月来有许多增量更新,这里提几个重点。
富有表现力的更新
Rust 过程宏是杀手锏,Toasty 大量使用以减少查询、创建、更新的样板。近期加入 update! 宏,可单次更新中设置 name 字段并递增 login_count,无需先加载数据。
文档字段
Toasty 不只用于关系数据。文档库常见,多数关系库(含 PostgreSQL)支持 JSON 等文档类型及查询。Toasty 加入一等支持:用 #[document] 标注 settings 字段,在 PostgreSQL 中编为 JSONB,过滤时用其 JSONB 查询能力。
多态关联
多态关联的目标可能是多种类型。Toasty 结合 enum 与常规关联实现:用 #[shared(id)] 和 #[index(id)] 注解描述表结构,共享 id 字段映射到同列并建索引。使用顺畅,可创建归属用户的项目、按用户过滤、再转移给团队。
未来方向
软件工程世界每三个月就大不同,终点未知。但我很兴奋,未来光明。Rust 或许不是终点,但旅程中必占重要角色。没有理由不能既高效又拥有运行快、内存小的优质应用。
Web 应用方面,我将继续用 Rust、Topcoat 和 Toasty 构建。想尝试可看入门指南,并到 Tokio Discord 的 #topcoat 频道交流。
评论
部分用户质疑在 Rust 中直接混合标记逻辑的可维护性与新术语“shard”设计,少数人看好 Topcoat 的 Rails 式方向;关于 AI 时代语言,反直觉地较多人认为语言选择已无关紧要。
担心在 Rust 中直接混合标记与逻辑会重蹈 PHP 覆辙
- 认为在语言内混写 markup 与逻辑长期增加维护难度,唤起 PHP 时代糟糕记忆(少数人)
- 对框架特有的事件绑定语法表示困惑(少数人) > 这种按钮语法到底是什么鬼(@Thaxll)
质疑新造术语“shard”而非沿用客户端/服务器注解
- 认为出色的工作中没必要发明新词,用明显的 client/server 标注更能降低新用户门槛(少数人) > 为什么不选显而易见的客户端/服务器注解而非定义新术语(@jazzypants)
对框架生产可用性与作者态度存疑
- 因开发方流露的态度问题,不敢在接近生产环境处采用(少数人) > 若这是他们的态度,我无法冒风险用在生产附近(@cube00)
看好 Topcoat 的 Rails 式集成方向但希望兼容现有生态
- Rails 背景开发者欣赏其消除客户端响应式样板、类似 LiveView 的思路,同时希望保留 Axum 等独立框架并存(少数人)
- 建议集成熟前端方案如 React 以提升对 AI 代理的友好度(少数人) > 喜欢它减少客户端响应式样板的方向(@lackoftactics)
认为直接用 Rust 写 Web 应用永远是小众
- 前端开发者普遍不愿为安全性能改写 Rust,大团队中直写 Rust 反馈慢、维护重,更倾向贴近原生标记的方案(少数人) > 除非必要不再直写 Rust 做 Web 应用(@excsn)
认为 AI 时代语言选择已无关紧要或由平台决定
- 较多意见指出 AI 代理编程下语法丑陋或阵营偏好无意义,结果、优化与平台适配才是核心,语言战争实际已终结(较多人) > 当人不在驾驶位,出租车手动或自动无关紧要(@pjmlp)
批评内置 ORM 多数据库抽象会泄漏
- 认为试图统一 SQL 与 NoSQL 的 ORM 必然遇到抽象漏洞,偏好更显式的查询工具(少数人) > 正确用 Dynamodb 和 Postgres 截然不同,强行抽象难调和(@cogman10)
有价值的补充
- 该框架的服务端组件思路类似 Phoenix 的 LiveView,并非全新概念(@victorbjorklund)
- 带自动资源管理的编译语言对分布式系统人体工学更佳且编译更快,Rust 更适合留在不允许自动管理的场景(@pjmlp)
- 用 C 加 LLM 剔除内存错误的调侃,折射对 Rust 安全必要性成本的质疑(@lolakutty)