【问题标题】:Understanding Apollo client caching and optimistic UI in AWS AppSync JavaScript SDK了解 AWS AppSync JavaScript SDK 中的 Apollo 客户端缓存和乐观 UI
【发布时间】:2019-02-12 18:10:37
【问题描述】:

我正在尝试使用 AWS AppSync JavaScript 开发工具包在 Apollo 客户端中实现缓存,但我首先很难理解使用缓存的最佳方式,其次如果我需要进行任何更改以使 Apollo V2 教程生效使用 AppSync SDK。

关于使用缓存,我有一个我得到的对象列表,然后我想查看和修改这个列表中的单个对象。有很多关于如何更新列表中的内容的教程,但我宁愿运行第二个查询,该查询通过其 ID 获取单个对象,以便页面始终可以正常工作,而无需先浏览列表。

缓存是否足够聪明,可以知道通过查询 Y 和 Z 获得的对象 X 是同一个对象并且将同时更新?如果没有,是否有任何文档说明如何编写更新来同时更新列表中的对象以及自身?

如果不存在任何文档,那么我将尝试自己解决并发布代码(因为它很可能不起作用)。

关于第二个问题,我已经让应用程序正常工作并使用 Amplify 查询 API 进行身份验证,但我不确定如何正确实现缓存。创建客户端时需要指定缓存还是SDK有内置缓存?如何访问缓存?只是像这些教程中那样通过查询客户端吗? https://www.apollographql.com/docs/react/advanced/caching.html

【问题讨论】:

    标签: javascript graphql apollo


    【解决方案1】:

    我先回答你的第二个问题:

    关于第二个问题,我已经让应用程序正常工作并使用 Amplify 查询 API 进行身份验证,但我不确定如何正确实现缓存。创建客户端时需要指定缓存还是SDK自带缓存?如何访问缓存?只是像这些教程中那样通过查询客户端吗?

    好的。所以这里有点麻烦——看起来 AppSync 是在 GraphQL 的主要客户端库(Apollo、Relay 等)进行大修时部署的,所以 AWS 实际上围绕 Apollo 客户端创建了一个包装器(可能是为了稳定的 API 目的)然后公开他们自己的做事方式。只是快速浏览一下代码,看起来他们有自己的专有和未记录的做事方式that involves websockets, their authentication protocols, a redux store, offline functionality, ssr, etc)。因此,如果herehere 没有明确解释,您就处于未知领域。

    幸运的是,他们提供的所有东西(以及更多)都现在记录的方式在底层 Apollo 客户端中实现了。更幸运的是,看起来 AppSync 客户端将大部分实际的 GraphQL 相关内容直接转发到内部 Apollo 缓存,并允许您在 cacheOptions 下传递配置选项,因此您可以使用 Apollo 客户端进行大部分配置可以使用 AppSync 客户端(更多内容见下文)。

    很遗憾,您无法使用 AppSync 客户端直接访问缓存(他们已将其隐藏以确保其公共 API 在波动的生态系统中保持稳定)。但是,如果您真的需要更多控制,他们在 AppSync 客户端中实现的大部分内容都可以轻松复制到您自己的 Apollo 客户端实例中,您可以在其中解锁完全控制(您可以使用 open-source AppSync code 作为基础)。由于 GraphQL 前端和后端是解耦的,所以没有理由不能使用自己的 Apollo 客户端连接 AppSync 服务器(对于一个大型、严肃的项目,这就是我会做的,因为 Apollo 客户端有更好的文档记录并正在积极开发中)。

    缓存是否足够聪明,可以知道通过查询 Y 和 Z 获得的对象 X 是同一个对象并且将同时更新?如果没有,是否有任何文档说明如何编写更新来同时更新列表中的对象并自行更新?

    第一部分涉及 Apollo 客户端和 AppSync 客户端。

    是的!这是 Apollo 客户端的一大优点 - 每次您进行查询时,它都会尝试更新缓存。缓存是规范化的键值存储,其中所有对象都存储在顶层,其中键是对象的__typenameid 属性的组合。 Apollo 客户端会自动将__typename 添加到您的所有查询中(尽管您必须手动将id 添加到您的查询中 - 否则它会退回到查询路径本身作为键[这不是很健壮]) .

    docs 很好地概述了该机制。

    现在,您可能需要做一些更高级的事情。例如,如果您的 GraphQL 架构使用 id 以外的某个唯一对象标识符,则您必须为映射到它的 dataIdFromObject 提供一些函数。

    此外,有时在进行查询时,缓存很难确切知道您要求在发出网络请求之前检查缓存的内容。为了缓解这个问题,他们提供了cache redirect 机制。

    最后,也许也是最复杂的一点,是如何在分页查询中更新内容的顺序(例如,有序列表中的任何内容)。为此,您必须使用@connection 指令。由于这是基于relay connection spec,我建议略读一下。

    奖励:要查看缓存的运行情况,我推荐Apollo client dev tools。这有点小问题,但它至少可以让您深入了解它在本地缓存中实际发生的情况——如果使用 AppSync,这将不起作用。


    所以除了以上关于设置和配置缓存的信息外,您还可以在应用运行时控制数据和对缓存的访问(如果直接使用 Apollo Client 而不是 AppSyncClient)。

    Direct Cache Access docs 指定可用的方法。但是,由于大多数更新仅根据您所做的查询自动发生,因此您不必经常使用这些更新。但是,它们的一种用途是用于复杂的 UI 更新。例如,如果您进行了从列表中删除项目的突变,而不是重新查询整个列表(这更新缓存,但会以更多的网络数据、解析和规范化为代价) 您可以使用readQuery/writeQueryupdate 突变选项定义自定义缓存更新。这也与optimisticResponse 配合得很好,如果您正在寻找乐观的 UI,您应该使用它。

    此外,您可以使用fetchPolicy or errorPolicy options 之一选择是要使用还是绕过缓存(或更高级的策略)。

    【讨论】:

    • 哇,非常感谢,这是一个令人难以置信的答案!一段时间以来,我一直认为迁移到普通的 Apollo 客户端是一个好主意,这证实了这一点。
    猜你喜欢
    • 2019-02-08
    • 2020-08-31
    • 2021-04-21
    • 2019-02-21
    • 2017-03-18
    • 2018-08-17
    • 2020-12-05
    • 2017-04-02
    • 2019-02-13
    相关资源
    最近更新 更多