Hacker News 中文摘要

RSS订阅

Topcoat 用 Rust 拓展服务端应用边界 -- Topcoat is pushing the boundary of server applications with Rust

两个月前,朱利安(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)