服务器驱动UI基础
使用SDUI减少客户端逻辑,提供跨客户端平台的统一性
服务器驱动UI(SDUI)是一种旨在通过从API返回产品信息而不是领域数据,来减少客户端逻辑并确保客户端平台(web、iOS、Android等)之间一致性的一种架构模式。这种方法适用于前端与后端团队之间可以协作,并且有强烈愿望在多个团队和组织之间构建一致体验的场景。
💡 技巧
有关高级模式和模式类型,请参阅更多SDUI主题。
架构目标
SDUI的主要需求来源于移动原生应用开发。这些平台需要将客户端应用的版本发布到应用商店,而商店通常有一个漫长的审查过程,新版本才能发布。然后,即使新应用版本发布后,用户也需要更新他们的版本才能开始使用或体验新功能。
如果您的API返回屏幕上的确切显示内容,您可以在不更新应用程序版本的情况下控制不同UI元素或文字。您还可以更改发送给API的输入,而无需进行任何应用程序更新。
当构建一个图形 采用由客户端团队使用的界面设计语言,通常希望将模式与设计语言结合。这需要一个明确的系统设计和一组组件来在前端渲染视图。
指导原则
SDUI 不是一个可以安装的框架或库。它是一种可以在不同的方式下实现,同时仍遵守相同核心原则的设计模式。
从UI设计开始
从您的UI设计开始,而不是查看数据模型或API响应。采用需求驱动的设计方案从客户端的角度编写您首选的查询。需求驱动的概念适用于任何客户端,但UI应用应直接从API响应与屏幕上的条目联系起来。
如果您发现自己正在描述从API到视图的步骤,这可能是一个警告信号,表明您必须在客户端中重复此逻辑。
减少现有客户端代码中的逻辑
确定并减少现有客户端代码中的任何逻辑。有人可能会将“逻辑”仅视为后端中的业务规则。然而,如果您曾因新功能或更新功能的工作方式而不得不更新条件或切换语句,那么您可以将这些前端部分视为“逻辑”。接受您的API响应并进行转换、连接或使用辅助函数的其他地方也是逻辑的额外警告信号。
如果您必须在一个客户端中更改此类型逻辑,您可能还需要在其他人中更改。您可以通过将逻辑移动到您的API来减少这种冗余。
返回产品信息,而不是域数据
产品信息包括UI组件的布局、外观和内容详情。域数据是原始或低级别的数据,代表应用程序的核心信息和业务逻辑。理想情况下,服务器应提供与客户端上UI元素的展示和行为相关的特定信息,而不是发送域数据。
您最有可能只需要API返回字符串,而不是枚举、布尔值或数字。通过仅返回字符串,服务器可以在后端处理所有问题,并向客户端返回格式化、本地化和准备好显示的文本。
使用可空字符串(String
与String!
)也是最佳实践。通过服务器控制的可空性,客户端代码可以直接使用API响应——如果存在一个字段,它将渲染该组件;如果不存在,则不执行任何操作。
使用设计系统
一旦所有客户端都以相同的方式使用您的API,您需要一个共享的语言,客户端应用可以使用它来渲染它们的视图。这正是设计系统的目的。拥有一个共享的设计系统,您可以规划一次API更改,并确信使用该设计系统的所有客户端都可以使用该API。
使用GraphQL类型定义您的功能
一旦拥有设计系统,下一步就是将其编码实现。您的服务器的 GraphQL模式 就是您可以对API的能力进行编码的地方。通过GraphQL查询,客户端仍然可以选择仅支持的功能或类型。
逐步采用SDUI
在遵循所有指导原则的情况下,团队可能会被诱惑通过一次性将所有内容都转变为服务器驱动来过度复杂化他们的应用程序。通过采取小而可控的步骤向SDUI迈进,您的团队能够平衡创新和稳定性,同时提升整体用户体验。
例如,您可以从在应用程序中实现单一UI组件或功能开始采用SDUI。这可以是一个简单的部件或应用程序的特定部分。这样,您可以在受控环境中测试水温,了解SDUI如何工作。
您还可以在保留现有前端的情况下,使用SDUI为应用程序的新特性或新部分服务。这样一来,您可以在不影响应用程序的遗留部分的同时,使用SDUI的新功能。
SDUI将加快未来特性的发布时间,但初始采用需要一些开销。
模式设计
以这个模拟电子商务模式为例,该模式允许客户端显示特色产品列表
type Product @key(fields: "id") {id: ID!name: StringformattedPrice: String# other product fields...}type ProductsCarousel {products: [Product]count: Int}type ProductsList {products: [Product]count: Int}type ProductsError {message: String!}union FeaturedProductsResponse = ProductsList | ProductsCarousel | ProductsErrortype Query {featuredProducts: FeaturedProductsResponse}
当 查询 Query.featuredProducts
,客户端可以根据 query 的结果渲染多个特定体验。您可以使用返回的 __typename
的值来确定是要渲染产品集合还是显示错误消息给用户。
fragment productFields on Product {idnameformattedPrice}query FeaturedProductsCollection {featuredProducts {__typename... on ProductsList {products {...productFields}}... on ProductsCarousel {products {...productFields}}... on ProductsError {message}}}
查看 SDUI模式设计 以获取更多设计模式。