JetBrains Blog 发布的一篇文章探讨了在 Kotlin 环境中使用 Compose HTML 构建由服务器渲染的 Web UI 的可能性。此时,多个框架正将部分 UI 处理重新转移到服务器。提议的想法是提供可复用且类型安全的 Compose 组件,而不是编写与应用代码分离的独立文本模板。文章强调,所提出的内容是对相关想法的探索,并非 JetBrains 的正式承诺,也不是 API 或路线图的声明。
这一设想源于对其他生态系统中出现的路径的比较:React 推出了服务器组件,HTMX 重新引起了人们对 hypermedia 模型的关注,而 Phoenix LiveView 证明了无需依赖客户端框架,也可以从服务器推送交互式更新。文章认为,JVM 生态系统拥有许多服务器端渲染库,但它们通常依赖模板语言,且没有提供足够接近 JavaScript 开发者所熟悉的组件概念的组件。
为什么选择 Compose HTML?
Compose Multiplatform 提供了一种一次编写业务逻辑和用户界面,并在 Android、iOS、桌面设备和 Web 之间共享的方式。不过,Compose Multiplatform 当前的 Web 目标依赖直接在 canvas 中进行渲染;文章指出,这会带来与搜索引擎优化、加载时间和可访问性相关的成本。
Compose HTML 比 Compose for Web 更早出现,它使用 Compose Runtime 以 Kotlin 构建单页应用,然后通过 Kotlin/JS 编译器将其转换为 JavaScript。文章建议为其添加 JVM 目标,使其能够执行服务器端渲染:这样便可以使用真正的组件和类型,在 Kotlin 中直接生成 HTML 树,而无需独立的模板语言。
来源通过 Thymeleaf 中编写的卡片组件与 Compose 组件进行对比示例。在基于模板的模型中,卡片定义在独立文件中,参数以不参与类型检查的字符串形式传递。而在 Compose 中,卡片是一个 typed 函数,接收 String 类型的标题和 Int 类型的数字。因此,修改参数名称会通过开发环境更新所有使用位置,或者在编译期间产生错误;传入错误类型也会导致编译器报错,而不是在运行期间出现意外。
服务器端渲染设想
所提出的设想需要添加 renderToString 和 renderToBytes 等函数,在 JVM 上执行一次 composition,然后将生成的树转换为 HTML 文本或字节数据。根据文中的示例,该过程会创建文本和容器元素等组件,等待初始组合稳定下来,然后遍历生成的树并将其转换为 HTML,全程不需要浏览器或 DOM。
这种模型存在明显限制。它很可能只支持单次渲染阶段,不支持状态变化时的重组或执行副作用,因此接近 JavaScript 框架中的服务器端渲染概念。组件可以接受事件监听器,但这些监听器在服务器上将处于非活动状态,因为在服务器生成 HTML 时,绑定浏览器事件没有意义。
文章设想使用 Spring Boot 构建一个完整的任务应用:GET 路由渲染任务页面,而 POST 请求则添加新任务或更改任务状态。在这一场景中,交互将依赖发送真实的 HTTP 表单并重新加载页面,不使用客户端 JavaScript;这类似于使用 Thymeleaf 的传统渲染应用,但整个界面都在 Compose 中编写。
当前生态与潜在框架
Compose HTML 目前只有 JS 目标,因此不提供服务器端渲染。不过,文章指出,围绕 Compose Web 已形成活跃的生态。Kobweb 构建于 Compose HTML 之上,支持静态网站导出和预渲染,以帮助改善搜索引擎优化,但不提供 SSR。Kilua 则直接依赖 Compose Runtime 来执行 SSR 和 CSR,并提供与 Ktor、Spring Boot 及其他框架的集成;Summon 也提供 SSR 和 hydration 支持。
文章认为,为 Compose HTML 添加 SSR 能力,可能会为 Kobweb、Kilua 和 Summon 提供共同基础,而不是让它们依赖三条相互分离的路径。这也可能为 Spring Boot 和 Ktor 框架提供在服务器上集成 Compose HTML 的实际理由。不过,这一结果并没有得到保证或正式宣布;文章将其描述为一种需要通过实验并确定所需集成点的潜在方向。
初始渲染之后
探索随后转向 hydration 和状态同步问题:在服务器上渲染的组件如何继续在浏览器中执行交互?服务器和客户端是否需要就状态达成一致?文章指出,解决这些问题可能实现双方之间的界面代码共享,使同一个组件能够分别为浏览器和服务器进行编译,并支持完全使用 Kotlin 编写的、完整的交互式 Web 应用。
不过,这一设想并不建议将 Compose HTML 转变为一个包含全部组件和操作、可以直接使用的完整框架。正如来源所说明的,更接近的目标是保持核心足够小,并将框架集成和生态库的构建留给社区,这类似于 React 的方式,但应用于一个多平台库。这不同于 Compose Multiplatform 的其他部分,后者为 Material3、状态管理等提供了官方库。
据文章介绍,目前正在与 Kobweb、Kilua 和 Summon 的开发者进行交流,以收集他们的意见;Spring 团队在 Compose HTML 添加 JVM 目标后,也表示有兴趣进行尝试。因此,这一设想目前的价值在于确定 JVM Web 开发的潜在方向,而不是提供一款可用产品或已确认的功能。如果这一想法继续发展,主要挑战将是平衡核心的简洁性、与服务器框架的集成,以及客户端与服务器之间的交互需求和组件复用。