Shop Store 团队位于 Shopify 的 Shop 组织内,负责管理Shop App商店屏幕上的买家体验——买家可以在该屏幕上查看商家的产品和系列。我们最近实施了一种称为服务器驱动 UI 的架构,它允许我们控制要为商家商店显示哪些商店部分。
在实现服务器驱动的 UI 之前,Store Screen 的显示逻辑完全是客户端驱动的。在客户端-服务器架构的上下文中,这意味着商店客户端负责处理 UI 的所有方面,包括商店屏幕的布局、视觉设计元素以及要呈现的 UI 组件。
作为我在Dev Degree 项目中第三次实习的一部分,我作为移动开发实习生加入了 Shop Store 团队。在这个角色中,我有机会使用服务器驱动的 UI 架构共同推动构建新的 Store Screen。这段经历教会了我如何设计和实施可扩展的移动设计模式,以及交付高质量的生产代码。我还克服了技术挑战,例如在现有团队的服务器驱动 UI 组件或创建 Shop Store 特定组件之间做出决定,以及弄清楚如何支持旧客户端版本不熟悉的布局或部分。这篇文章讨论了我的团队如何在 Store Screen 上实现服务器驱动的 UI 架构、我学到的经验教训以及我在构建此架构时克服的挑战。
为什么服务器驱动的 UI 有意义
以前使用客户端驱动的显示逻辑,Store Screen 为所有商店呈现相同的商店布局和组件,而不管商家的规模或可用产品的数量:
Server-Driven UI 之前的默认 Store Screen 布局
客户驱动架构出现的一个问题是商店布局无法根据个别商家的需求进行定制。例如,对于拥有许多产品的商家,显示“畅销商品”部分是合适的,因为预计一小部分商品会比其他商品卖得更好。然而,对于产品很少的商家,独立的“畅销商品”部分没有意义,因为它会与主要产品列表重复。
鉴于静态的、客户端驱动的 UI 的性质,我们在启动新实验的频率和时间上受到限制,因为我们受到每周发布节奏的约束。另一方面,服务器驱动的 UI 架构允许我们在我们认为必要的时候启动实验,并为商家跨不同的模板和布局运行这些实验。这是因为后端能够控制当前正在运行哪些实验,以及要为商家显示哪些模板和布局。
Store Screen 的客户端驱动实现的另一个问题是,如果在将版本推送给用户后发现呈现问题,则推送修复所需的时间线。由于 Shop App 的发布过程每周进行一次,因此客户端的任何修复都需要长达一周的时间才能上线。
在服务器驱动的 UI 架构中,服务器端负责通知客户端要呈现的商店部分(例如:畅销商品、新品、所有产品)和布局( 格或货架)。这种服务器驱动的 UI 架构的主要目标是使商家商店能够根据其不同的需求进行个性化设置。这将通过模板化的商店布局来执行,这将呈现商家所需的部分。
这种架构还允许团队同时为多个商家进行多个实验,以便更好地了解他们的行为。随着时间的推移,这些实验使团队能够制作出最好的商店版本。
此外,服务器驱动的 UI 架构还确保商店的某些方面不依赖于应用程序的发布。例如,如果在商店中呈现的其中一个部分存在问题,则可以在后端实施更改以确保不会为商家显示该部分,并且可以在未来的应用程序版本中修复该问题。
下面的产品设计图片显示了所有商家的默认模板,但有一些变化。“Best Sellers”部分呈现为具有较大显示类型的产品 格。Store Screen 还呈现一个“All Products”部分,以小显示类型显示产品 格,以及一个“Shop All Products”操作,它将买家带到一个包含所有产品的屏幕。默认模板的另一个变体是具有集合的商店,集合是属于一个类别的一组产品。属于一家商店的产品系列呈现为具有小型显示类型和“查看全部”操作的产品货架,该操作将买家导航到显示所有产品系列的另一个屏幕。
具有大型显示类型和“查看全部”操作的产品 格。
具有小型显示类型和“购买所有产品”操作的产品 格。
具有小型显示类型和“查看全部”操作的 CollectionShelf。
仔细观察架构
服务器端的架构由模板处理层、编排器、数据加载层和商店服务器(以前称为 Arrive-Server)GraphQL 层组成。
服务器驱动的 UI 的服务器端架构。
以下是每一层的细分:
模板处理层:包含一个硬编码模板,它描述了商店默认模板中包含的部分类型。该层还具有来自商家的自定义项,这些自定义项指定了他们希望在其商店中可见的内容。模板元数据读取器从商户数据库中读取静态模板和商户特定模板,并返回要呈现的部分。
数据加载层SectionDataLoader:在提供所需的部分后,为每个要呈现的部分创建一个对象。该SectionDataLoader对象包含用于获取部分数据的所有逻辑。
GraphQL Layer : 将SectionDataLoader对象映射到相应的 GraphQL 类型,并为 Shop App 解析类型和字段。
编排层:编排模板处理层、数据加载层和 GraphQL 层之间的整个流程,并为每一层传递预期的信息。
在服务器端,GraphQL API 允许执行商店部分查询,这会返回 shop 商店的部分列表。每个部分都是从基本部分类型构建的,并且一个部分可以进一步定义为ProductsSection或CollectionsSection。该ProductsSection类型用于返回产品列表的部分,例如“所有产品”、“畅销产品”或“趋势”。另一方面,CollectionsSectiontype 用于返回集合列表的部分。还定义了具有可配置大小属性的各种布局类型,例如 GridLayout 和 ShelfLayout。 格布局支持具有大型产品块的 2×2 格或具有中型产品块的 3×3 格。货架布局允许用户向右滚动,并支持小型或大型产品块。在部分上拥有此布局属性使我们能够轻松创建新的方式来显示实体,而无需创建全新的部分。
在客户端,组件的渲染由以下组件架构处理:
服务器驱动的 UI 的客户端架构。
我们首先有一个名为 的顶级组件ServerDrivenStoreScreen,当买家想要查看商家的商店时,他们会被导航到该组件。对于商店屏幕中的每个部分(“系列”、“畅销书”、“所有产品”),我们渲染StoreSectionContainer组件。除了呈现此组件外,ServerDrivenStoreScreen还会呈现商店标题、导航栏和产品搜索栏。
然后StoreSectionContainer根据提供给它的部分类型确定要呈现的部分。如果部分类型是产品,StoreSectionContainer则将呈现ProductSection组件。否则,如果部分类型是集合,StoreSectionContainer则将呈现CollectionsSection组件。该组件将根据从服务器传递的显示类型ProductsSection呈现ProductShelf或组件。ProductGrid该组件还向/组件ProductsSection提供回调函数,在按下产品时导航到 ProductDetails 页面。ProductGridProductShelf
该CollectionsSection组件呈现一个CollectionShelf组件以显示产品集合。该组件还向在按下集合时CollectionShelf导航到屏幕的组件提供回调函数。CollectionDetails该ProductGrid组件呈现产品 格,还支持大尺寸和小尺寸显示。最后,ProductShelf和CollectionShelf组件都呈现一个可以向右滚动的产品或集合的货架。
为了获得组件所需的所有数据,将进行两次主要的 GraphQL 调用。第一个 GraphQL 调用是一个StoreSections查询,它获取StoreSections用于呈现商店所有部分的数据。这个调用是在ServerDrivenStoreScreen使用StoreSections钩子中进行的,返回的存储部分数据被传递到各个子组件。
第二个 GraphQL 调用是一个现有ShopInfo查询,它从缓存中预取数据以填充存储标头。此调用是在
ServerDrivenStoreScreenusinguseStoreInformation挂钩中进行的,StoreHeader 组件在ServerDrivenStoreScreen.
通过对开发学位的影响来学习
作为开发学位实习生,我致力于构建ProductGrid、ProductsSection和StoreSectionContainer组件,并创建StoreSections查询和useStoreSections挂钩。处理架构各个层的组件让我对 Shop 客户端架构有了更深入的了解。我还能够利用从之前的 Dev Degree 实习中获得的 React 知识,并将它们应用到这个项目中。
除了我从事的客户工作外,我还参与了关键决策制定,例如确定是否重用现有团队的服务器驱动 UI 组件或创建 Shop Store 特定组件。为了克服这一挑战,我和我的团队为这两种方法创建了一个优缺点列表。我们决定在需要时创建我们自己的 Shop Store 组件,因为这将使我们能够控制每个部分中的数据类型,并重用任何可以轻松解耦的组件。
我和我的团队克服的另一个挑战是弄清楚如何支持旧客户端版本不熟悉的布局类型或部分类型。我们通过再次创建一个优缺点列表来解决这个问题,该列表从后端和客户端的角度分析了所有的好处和后备方案。最后,我们决定由客户负责决定如何处理查询提供的布局/部分。客户端将为每个部分定义一个默认布局,如果客户端收到它不理解的新布局类型,则会呈现此默认布局。
总的来说,实施服务器驱动的 UI 可以让商家在他们想要如何个性化他们的商店方面处于主导地位。该架构还使 Shop 能够为新买家和回头客量身定制购物体验,并提供更加个性化的体验。这提供了找出在各种情况下吸引买家的机会。服务器驱动的 UI 还解锁了多项新功能,例如能够同时在不同的模板中运行不同的实验,并为买家更新 UI,而无需发布新的应用程序版本。作为一个开发团队,这确保了团队拥有一个可以随着时间的推移与产品一起成长的系统。我们希望这种服务器驱动的 UI 架构可以被 Shop 的其他团队所利用和广泛实施。
我要感谢 Shop Store 开发团队在整个项目中提供的持续支持和技术知识。作为一名 Dev Degree 实习生,这种领导客户工作的经历使我能够在我的团队中承担更大的技术责任,并帮助我磨练我的技术能力和项目管理技能。这段经历使我成为了一名更好的开发人员,我期待着不仅将我所学的知识应用到未来在 Shopify 的职位上,而且还用于我的计算机科学学位。
Ashwin Narayanan是卡尔顿大学开发学位课程的四年级实习生和计算机科学专业的四年级学生。您可以在GitHub 上关注他的工作。
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!