使用Apollo重写部分GraphQL查询的最佳实践?

时间:2018-01-02 20:24:28

标签: javascript reactjs graphql apollo react-apollo

我有以下react-apollo - 包装的GraphQL查询:

user(id: 1) {
  name
  friends {
    id
    name
  }
}

以语义表示,它会提取ID为1的用户,返回其name,并返回其所有朋友的idname

然后我在如下组件结构中呈现它:

graphql(ParentComponent)
  -> UserInfo
  -> ListOfFriends (with the list of friends passed in)

这一切都对我有用。但是,我希望能够为当前用户重新获取朋友列表。

我可以在父组件上执行this.props.data.refetch(),并且会传播更新;但是,我不确定这是最好的做法,因为我的GraphQL查询看起来更像是这样,

user(id: 1) {
  name
  foo1
  foo2
  foo3
  foo4
  foo5
  ...
  friends {
    id
    name
  }
}

虽然我唯一希望重新获取的是朋友名单。

干净地构建这个的最佳方法是什么?我正在考虑将最初跳过的GraphQL提取器绑定到ListOfFriends组件,这可以在必要时触发,但是想要了解如何最好地完成此操作。

提前致谢。

1 个答案:

答案 0 :(得分:11)

我不知道为什么你的问题被贬低,因为我认为这是一个非常有效的问题。 GraphQL的一个卖点是“一次性获取更少”。客户可以从后端非常简单地决定它需要什么。使用以前需要多个端点的深层嵌套图形查询现在可以在单个查询中表示。同时可以避免过度取样。现在你发现自己有一个大查询,一切都加载,并且没有n + 1个查询瀑布。但是现在您知道大查询中的一些字段可能会随时更改,并且您希望使用服务器中的新数据主动更新缓存。 Apollo提供了refetch字段,但它加载了整个查询,这显然是 overfetching ,这些查询已经卖给我,因为GraphQL中不再是一个问题。让我提供一些解决方案:

过早优化?

  

真正的问题是程序员花了太多时间在错误的地方和错误的时间担心效率;过早优化是编程中所有邪恶(或至少大部分)的根源。 - Donald Knuth

有时我们会尝试优化太多而不先测量。先写一下简单的方法,然后看看它是否真的是一个问题。究竟什么慢?网络?查询中的特定字段?查询的大小?

在你分析了究竟什么是慢的之后我们可以开始研究改进了:

Refetch和include / skip指令

使用directives,您可以根据变量从查询中排除字段。 refetch function can specify different variables比初始查询。这样,您可以在重新获取查询时排除字段。

拆分查询

单页应用是个好主意。 HTML是在客户端生成的,页面不必花费昂贵的时间去服务器来呈现新页面。但很快SPA就变得很大,代码分裂成为一个问题。现在我们基本上回到服务器端渲染并将应用程序拆分成页面。这同样适用于GraphQL。有时查询太大,应该拆分。您可以拆分UserInfoListOfFriends的查询。在缓存中,字段将被合并。使用query batching,两个查询都将在同一请求中发送,并且一个GraphQL服务器可以正确实现每个请求资源缓存(例如,使用Dataloader)几乎不会发现差异。

订阅

也许你已经准备好使用订阅了。订阅从服务器发送已更改字段的更新。这样您就可以订阅用户的朋友并实时获取更新。好消息是Apollo Client,Relay和许多服务器实现已经为订阅提供支持。坏消息是它需要的websockets通常会对您的技术堆栈提出不同于纯HTTP的要求。

withApollo() - > this.client.query

这应该只是你的最后手段!使用react-apollowithApollo高阶组件,您可以直接注入ApolloClient实例。您现在可以使用this.client.query()执行查询。 { user(id: 1) { friendlist { ... } } }可用于获取好友列表并更新缓存,这将导致更新您的组件。这可能看起来像你想要的,但可能会在应用程序的后期阶段困扰你。

相关问题