A few days ago, Apollo announced a shiny new Apollo Client. Here at Catch, we use Apollo as the library to interface with GraphQL and therefore, all of our data, making it one of the most important libraries in our technical stack.
几天前,Apollo宣布了一个闪亮的新Apollo Client。 在Catch,我们使用Apollo作为与GraphQL以及因此与我们所有数据交互的库,使其成为技术堆栈中最重要的库之一。
By the way, if you’re a developer, I highly suggest following technologies you use on Twitter/Reddit/etc. New releases, features, and tutorials will magically appear in your timelines for your perusal 😃
顺便说一句,如果您是开发人员,我强烈建议您遵循Twitter / Reddit / etc等上使用的技术。 新版本,功能和教程将以神奇的方式出现在您的时间表中,供您仔细阅读😃
You can read their blog announcement here, but the gist of it is:
您可以在此处阅读他们的博客公告,但要旨是:
- Simplified dependencies/imports 简化的依赖关系/导入
- Updated cache APIs 更新了缓存API
- More reactivity React性更高
We were excited for all of this (‼️) and started the migration process, which I’ve detailed for you below.
我们为所有这些(!️)感到兴奋,并开始了迁移过程,下面将为您详细介绍。
迁移到Apollo Client 3 (Migrating to Apollo Client 3)
We followed along with the installation instructions from Apollo here.
在这里,我们遵循了Apollo的安装说明。
#1调整我们的依赖关系和导入 (#1 Adjusting our dependencies and imports)
One of the promises of the new version is simplified dependencies. The first step here is adding the new Apollo client
新版本的承诺之一是简化的依赖关系。 第一步是添加新的Apollo客户端
![Image for post](https://miro.medium.com/max/9999/1*5dzBFeJ5Q2RO-X8gmDFTNg.png)
Next, we went through our dependencies one by one to update them. We used several of the Apollo packages, so I’ll detail below what the process was like for each individually.
接下来,我们逐一检查依赖关系以更新它们。 我们使用了几个Apollo软件包,因此我将在下面详细说明每个过程的过程。
![Image for post](https://miro.medium.com/max/9999/1*VgjloYPNQiDjHvGjnSj0JA.png)
apollo-boostThis was not actually in use anywhere in our app, so we simply removed it from our package.json
file. 🙄
apollo-boost这实际上不在我们的应用程序中的任何地方使用,因此我们只是将其从package.json
文件中删除了。 🙄
apollo-clientWe were importing the Apollo Client in one mainApollo.js
file. This was as easy as changing the import to the updated package:
apollo-client我们正在一个主Apollo.js
文件中导入Apollo Client。 这就像将导入更改为更新的包一样简单:
![Image for post](https://miro.medium.com/max/9999/1*xQH2saKaBpjdTt5Wizo6-Q.png)
apollo-link and apollo-link-httpIn that same file, we adjusted the link packages to come from the new @apollo/client
library, then removed the old dependencies from our package.json
file. The new Apollo client has options for uri
headers
and credentials
directly on the client, if you don’t need a custom link. However, because we have some custom functionality for handling GQL errors, we kept our existing Link config.
apollo-link 和apollo-link-http在同一文件中,我们将链接包调整为来自新的@apollo/client
库,然后从package.json
文件中删除了旧的依赖项。 如果您不需要自定义链接,则新的Apollo客户端可以直接在客户端上提供uri
headers
和credentials
选项。 但是,由于我们具有一些用于处理GQL错误的自定义功能,因此我们保留了现有的Link配置。
![Image for post](https://miro.medium.com/max/9999/1*FWqzjwaJE6YE9K1ShY5osA.png)
apollo-link-*The rest of the add-on link packages have been moved into the @apollo/client
package as well. We use apollo-link-error
and apollo-link-context
for additional functionality on our link, so we converted them to their new respective homes (paths). We were then able to remove two more dependencies 💪
apollo-link- *其余的附加链接包也已移至@apollo/client
包中。 我们将apollo-link-error
和apollo-link-context
用于apollo-link-context
其他功能,因此我们将它们转换为各自的新位置(路径)。 然后,我们可以删除另外两个依赖项💪
![Image for post](https://miro.medium.com/max/9999/1*SlUcEBjxPhuQ3X8UC0MUAA.png)
Note: the migration docs mentioned that “Apollo Client 3 no longer allows @client
fields to be passed through a Link chain”. I made note of this, in case we needed to revisit this restriction.
注意:迁移文档提到“ Apollo Client 3不再允许@client
字段通过链接链传递”。 我注意到了这一点,以防万一我们需要重新考虑这一限制。
graphql-tagInstead of having to import gql
from the graphql-tag
package, it is now included in the base @apollo-client
library. It’s almost as if gql is essential for using Apollo 😉. A quick cmd-shift-F
for this import showed 288 results (essentially, every query and mutation definition) and we replaced them all with the updated import. Then, we were free to remove thegraphql-tag
package 👋
graphql-tag现在不必将其从graphql-tag
包中导入gql
,它现在已包含在基础@apollo-client
库中。 几乎好像gql对于使用Apollo essential是必不可少的。 快速导入的cmd-shift-F
显示了288个结果(基本上是每个查询和突变定义),我们将它们全部替换为更新的导入。 然后,我们可以随意删除graphql-tag
包👋
![Image for post](https://miro.medium.com/max/9999/1*U6d7iZdkh9oLwfpX4JEtgQ.png)
react-apollo
React阿波罗
I found this very interesting: the
react-apollo
package was deprecated and its functionality wrapped into Apollo 3. For folks using Vue or Angular, you can import the ApolloClient from@apollo/client/core
instead. However, this move definitely speaks to React as a pseudo-default framework.我发现这很有趣: 不推荐使用
react-apollo
软件包,并将其功能包装到Apollo 3中。对于使用Vue或Angular的人员,您可以改为从@apollo/client/core
导入ApolloClient 。 但是,这一举动无疑将React作为伪默认框架。
Back to our migration — I split this into a couple pieces:
回到我们的迁移-我将其分为几部分:
Good 👍We have two custom hooks — useQuery
and useMutation
— which use the Apollo hooks, but also implement some extra sauce like logging and formatting. Therefore, we only had to change each of these in one spot. Nice.
好的👍我们有两个自定义的钩子( useQuery
和useMutation
,它们使用Apollo钩子,但也实现了一些额外的功能,例如日志记录和格式化。 因此,我们只需要在一处更改所有这些。 真好
![Image for post](https://miro.medium.com/max/9999/1*SJQ7hp3kQx11gtAQ2uusOA.png)
Bad 👎Not all of our queries/mutations have been updated to use these hooks. Previously, we were using containers for these, so we had to find-and-replace all instances of the container-based queries/mutations.
错误👎并非所有查询/突变都已更新为使用这些挂钩。 以前,我们使用容器来实现这些功能,因此我们必须查找并替换基于容器的查询/变异的所有实例。
![Image for post](https://miro.medium.com/max/9999/1*zs9XS0A3WuZ1JbzJaCOFQA.png)
Another one:We almost forgot one more import coming from react-apollo
The ApolloProvider
now comes directly from @apollo/client
as well. Make sure that for testing purposes, you’re using the MockedProvider
@apollo/client/testing
as well.
另一个:我们几乎忘记了再有一个来自react-apollo
的ApolloProvider
现在也直接来自@apollo/client
。 确保出于测试目的,您还使用了MockedProvider
@apollo/client/testing
。
![Image for post](https://miro.medium.com/max/9999/1*TgHDd05SUnORKyJ7VNxpOQ.png)
apollo-utilities, apollo-cache-persistNot being used anywhere for us, simply removed these.
apollo-utilities,apollo-cache-persist不在我们任何地方使用,只需将其删除。
apollo-cache-inmemoryAs you may have guessed by now, this has also been moved to @apollo/client
proper. However, we ran into a bit of a hiccup here, as there’s a note that some things in our config (fragment matcher, dataIdToObject) have been deprecated. So for now, I moved InMemoryCache
and removed the deprecated pieces.
apollo-cache-inmemory您可能已经猜到了,它也已经移到@apollo/client
适当的位置。 但是,在这里遇到了一些麻烦,因为有一点说明,我们的配置(片段匹配器,dataIdToObject)中的某些内容已被弃用。 所以现在,我移动了InMemoryCache
并删除了不赞成使用的部分。
At this point, everything is using the new @apollo/client
and we’re down from 13 different dependencies to only 1 dependency. Pretty cool 😎
此时,一切都在使用新的 @apollo/client
,我们从13个不同的依赖项减少到只有1个依赖项。 很酷😎
#2关键时刻 (#2 Moment of truth)
Up to this point, I’ve just been replacing everything. I start the app locally, go to the home page, and unfortunately, this is what it looks like…
到目前为止,我一直在替换所有内容。 我在本地启动该应用程序,然后转到主页,很遗憾,它是这样的……
![Image for post](https://miro.medium.com/freeze/max/9999/1*NudVqe8TnYMoGFPBfL4KHg.gif)
I can see from the networks tab that we’re making all of the requests for the home page over and over again, plus we have some recurrent warnings in the log from Apollo that look like this:
我可以从“网络”标签中看到,我们一次又一次地提出了所有对主页的请求,此外,在Apollo的日志中还出现了一些类似以下内容的周期性警告:
Missing cache result fields: ...
We are able to narrow it down to two main issues:
我们可以将其缩小为两个主要问题:
Our root query is
viewer
so all queries go through the viewer object. Since the viewer doesn’t have any ID, the cache has no way to know that the next query usingviewer
is the same viewer as before (and for our purposes, is always the same).我们的根查询是
viewer
因此所有查询都通过查看器对象。 由于查看器没有任何ID,因此缓存无法知道使用viewer
的下一个查询与以前的viewer
相同(就我们的目的而言,始终是相同的)。For other queries that don’t have a unique ID, we need to specify with the cache how to identify it. For our
Recommendations
type, we can use thecreatedOn
timestamp as the unique identifier.对于其他没有唯一ID的查询,我们需要与缓存一起指定如何识别它。 对于“
Recommendations
类型,我们可以使用createdOn
时间戳作为唯一标识符。
We can resolve both of these issues using the typePolicies
option when declaring our cache. For the root viewer, we can automatically merge all incoming/existing data in the viewer. For the recommendations, we provide the unique key for Apollo to use. It ends up looking like this:
声明缓存时,我们可以使用typePolicies
选项解决这两个问题。 对于根查看器,我们可以自动合并查看器中的所有传入/现有数据。 对于建议,我们提供了供Apollo使用的唯一密钥。 最终看起来像这样:
![Image for post](https://miro.medium.com/max/9999/1*j4UYWfty1hMmOg7H_WkEYA.png)
and our home page is back to normal:
并且我们的主页恢复正常:
![Image for post](https://miro.medium.com/max/9999/1*v5OK_BCK9ukW5s5C625PEg.png)
After this, I’ll be walking through our entire app to see if there are any more keyFields
that should be added to our typePolicies
之后,我将遍历整个应用程序,以查看是否应将其他keyFields
添加到我们的typePolicies
结论 (Conclusion)
- Pretty painless migration (thanks Apollo!) 非常轻松的迁移(感谢阿波罗!)
- Excited to make use of new features 💪 激动地利用新功能💪
Nice to have our dependencies pared down, especially because it’s easier for us to see what we’re actually using.
减少依赖关系很高兴,尤其是因为它使我们更容易了解实际使用的内容。
翻译自: https://medium.com/trycatch/apollo-client-3-2e2379baf815