迁移到 Apollo Client 3.0
本文将引导您将应用程序从先前版本的 Apollo Client 迁移到Apollo Client 3.0。
为了说明迁移过程,我们还制作了这个视频,它使用我们全栈快速入门作为起点,将版本从 Apollo client 2.6 升级到 3.0:
3.0 新特性
- Apollo Client现在作为
@apollo/client
包分发(先前版本作为apollo-client
分发)。 - 该
@apollo/client
包包含 React 钩子和 GraphQL 请求处理,这些之前需要安装单独的包。 - Apollo Client 的缓存(
InMemoryCache
)更灵活、性能更高。它现在支持垃圾收集,存储规范化和非规范化数据,以及使用新的TypePolicy
和FieldPolicy
API 对缓存数据进行自定义。 - 此外,更新还包括大量错误修复和优化,详见变更日志。
安装
注意: Apollo Client 3.0 是一个重大版本发布,它包括 破坏性更改。如果您正在将现有应用程序更新到使用 Apollo Client 3.0,请参阅 变更日志 以了解这些更改的详细信息。
使用以下命令安装 Apollo Client 3.0:
npm install @apollo/client
如果您在已使用较早版本的 Apollo Client 的项目中安装 Apollo Client 3.0,请按照适用于您当前使用的库的每个部分的 更新导入 中的说明执行。
更新导入
@apollo/client 库包括以前需要安装其他包的功能。作为迁移到 Apollo Client 3.0 的一部分,请按照以下说明为您的应用程序当前使用的每个库执行以下操作。
为了简化将您的 import
声明从旧包转换为 @apollo/client
的过程,我们提供了一个基于 jscodeshift
的自动化 转换。请注意,此转换仅将 import
指令在不同 import
声明之间移动,而不检查导入值的正确使用。由于转换无法处理所有内容,请仔细关注 TypeScript 或您的打包工具产生的任何错误,并确保验证转换所做的所有更改。有关注意事项的更详细列表,请参阅 README.md
。
@apollo/react-hoc 和 @apollo/react-components
React Apollo HOC 和组件功能现在包含在 @apollo/client
包中:
import { Query, Mutation, Subscription } from '@apollo/client/react/components';import { graphql } from '@apollo/client/react/hoc';
作为迁移的一部分,我们推荐移除所有 @apollo/react-hoc
和 @apollo/react-components
依赖。
@apollo/react-hooks
所有 @apollo/react-hooks
功能都已包含在 @apollo/client
包中。例如:
import { ApolloProvider, useQuery, useApolloClient } from '@apollo/client'
作为迁移的一部分,我们推荐移除所有 @apollo/react-hooks
依赖。
破坏性变更
useQuery
不再保留使用新数据加载时先前提取的结果在它的data
结果中。相反,当正在加载新数据时(即loading
===true
),useQuery
的data
结果将被设置为undefined
。使用previousData
结果作为连接到旧版 v2 行为的桥梁。useQuery
的refetch
功能在 3.5.x 版本中坏了,直到 3.5.8 版本修复。在当前版本之前,如果使用了skip: true
选项,refetch
将总是undefined
。
@apollo/react-ssr
React Apollo 的 SSR 工具(如 getDataFromTree
、getMarkupFromTree
和 renderToStringWithData
)已包含在 @apollo/client
包中。通过 @apollo/client/react/ssr
访问它们:
import { renderToStringWithData } from '@apollo/client/react/ssr';
作为迁移的一部分,我们推荐移除所有 @apollo/react-ssr
依赖。
@apollo/react-testing
React Apollo 的测试工具(如 MockedProvider
)已包含在 @apollo/client
包中。通过 @apollo/client/testing
访问它们:
import { MockedProvider } from '@apollo/client/testing';
作为迁移的一部分,我们建议移除所有 @apollo/react-testing
相关依赖。
apollo-boost
Apollo Boost 项目现已停产,因为 Apollo Client 3.0 提供了类似直接的设置。我们建议移除所有 apollo-boost
相关依赖,并根据需要修改您的 ApolloClient
构造函数。
apollo-client
使用 Apollo Client 3.0,apollo-client
包已停产,取而代之的是 @apollo/client
。作为迁移的一部分,请移除所有 apollo-client
相关依赖。
apollo-link and apollo-link-http
所有 apollo-link
、apollo-link-http
和 apollo-link-http-common
的功能都包含在 @apollo/client
包中。例如:
import { ApolloLink, HttpLink, from, split, execute } from '@apollo/client';
作为迁移的一部分,我们建议移除所有 apollo-link
、apollo-link-http
和 apollo-link-http-common
相关依赖。
如果您想配置自己的链接链,ApolloClient
构造函数仍然接受链接选项。否则,ApolloClient
构造函数现在也支持 uri
、headers
和 credentials
选项。例如:
const client = new ApolloClient({cache,uri: 'https://127.0.0.1:4000/graphql',headers: {authorization: localStorage.getItem('token') || '','client-name': 'Space Explorer [web]','client-version': '1.0.0',},...});
这些选项在幕后传递给新的 HttpLink
实例,然后 ApolloClient
就会被配置为使用该实例。
apollo-link-*
之前在 https://github.com/apollographql/apollo-link 存储库中维护的独立 apollo-link-*
包已合并到 Apollo Client 项目中。现在这些链接都有自己的嵌套 @apollo/client
入口点。导入项应更新如下:
apollo-link-batch
现在为@apollo/client/link/batch
apollo-link-batch-http
现在为@apollo/client/link/batch-http
apollo-link-context
现在为@apollo/client/link/context
apollo-link-error
现在为@apollo/client/link/error
apollo-link-retry
现在为@apollo/client/link/retry
apollo-link-schema
现在为@apollo/client/link/schema
apollo-link-ws
现在为@apollo/client/link/ws
需要注意的是,Apollo 客户端 3.0 不再允许 @client
字段通过链接链传递。尽管 Apollo 客户端 2.0 允许拦截 @client
字段,如 apollo-link-state
和 apollo-link-schema
中的链接字段的拦截,但 Apollo 客户端 3.0 强制要求 @client
字段仅本地有效。这有助于确保 Apollo 客户端 的本地状态故事更容易理解,并防止无意中将在网络请求中出现的字段(PR #5982)。
graphql-anywhere
GraphQL Anywhere 包的功能现在不再包含在 Apollo 客户端中。您还可以继续使用 graphql-anywhere
包,但 Apollo 将不再使用它,也不会再主动支持它。
graphql-tag
在 @apollo/client
包中,graphql-tag
被作为一个依赖项,并导出 gql
。为了简化依赖项,我们建议从 @apollo/client
导入 gql 并删除所有 graphql-tag
依赖项。
react-apollo
react-apollo
v3 是一个导出以下包的聚合包:
@apollo/react-common
@apollo/react-hooks
@apollo/react-components
@apollo/react-hoc
@apollo/react-ssr
@apollo/react-testing
已弃用 react-apollo
包,上述每个包的功能现在都可以从 @apollo/client
直接访问:
@apollo/react-hooks
-> 现在可以直接从@apollo/client
@apollo/react-components
-> 现在可以从@apollo/client/react/components
@apollo/react-hoc
-> 现在可以从@apollo/client/react/hoc
@apollo/react-ssr
-> 现在可以从@apollo/client/react/ssr
@apollo/react-testing
-> 现在可以从@apollo/client/testing
使用 Apollo Client 3.0 的独立组件
Apollo Client 3.0 提供了多个入口点供您导入。如果您仅使用 Apollo Client 功能的某个特定部分,则可以从中相应入口点导入该功能。这样做现代打包器可以省略 @apollo/client
包的其余部分,从而大大减少其大小。
不使用 React 使用 Apollo Client
Apollo Client 3.0 包含对 React Hooks 的内置支持,但它仍然完全支持非 React 视图层。要使用 Apollo Client 3.0 与 Vue、Angular 或您选择的任何其他视图层一起使用,请从 @apollo/client/core
入口点导入 ApolloClient
:
import { ApolloClient } from '@apollo/client/core';
不使用 Apollo Client 的其余部分使用 apollo-utilities
Apollo 实用工具包已被移除,但您可以从 @apollo/client/utilities
入口访问这些实用工具 themselves:
import { isReference, isInlineFragment } from '@apollo/client/utilities';
使用 Apollo 缓存和/或 Apollo 缓存内存不使用 Apollo 客户端的其他部分
Apollo 缓存 (apollo-cache
) 和 Apollo 缓存内存 (apollo-cache-inmemory
) 包已被移除,但如果您想独立使用 Apollo 客户端的缓存,可以使用 @apollo/client/cache
入口访问他们的内容:
import { ApolloCache, InMemoryCache } from '@apollo/client/cache';
缓存改进
Apollo 客户端 3.0 引入了其缓存系统的强大改进。大多数这些改进是向后兼容的,因此大多数应用程序在没有任何更改缓存逻辑的情况下将继续工作。然而,我们强烈建议您了解更多关于 Apollo 客户端 3.0 缓存的功能。
破坏缓存更改
以下缓存更改 不是 向后兼容。在升级到 Apollo 客户端 3.0 之前请考虑这些更改。
默认情况下,
InMemoryCache
不再合并两个对象的字段,除非这些对象具有相同的唯一标识符并且该标识符存在于两个对象中。此外,同名字段的值默认不再递归合并。您可以为特定字段定义自定义merge
函数来处理这两个更改。您可以在 合并非规范化对象 中了解更多关于这些更改的信息。(PR #5603)。所有缓存结果现在都是冻结的/不可变的,正如在 Apollo 客户端 2.6 博文中承诺的那样(PR #5153)。
FragmentMatcher
、HeuristicFragmentMatcher
和IntrospectionFragmentMatcher
全部已被移除。我们建议使用InMemoryCache
的possibleTypes
选项。更多详细信息,请参阅手动定义possibleTypes(PR #5073)。缓存中规范化数据的内部表示已更改。如果您使用
apollo-cache-inmemory
的公共API,则这些更改不应影响您。如果您直接操作缓存数据,请查看PR #5146以获取详细信息。client|cache.writeData
已完全移除。可以使用client|cache.writeQuery
、client|cache.writeFragment
和/或cache.modify
来更新缓存。例如:client.writeData({data: {cartItems: []}});可以转换为
client.writeQuery({query: gql`query GetCartItems {cartItems}`,data: {cartItems: []}});有关移除
writeData
的原因的更多详细信息,请参阅PR #5923。cache-and-network
的获取策略现在在缓存更新影响查询时启动网络请求,并且不再仅限于在查询首次运行时。为了重新创建从2.x.x
的默认行为,请配置一个nextFetchPolicy
(在>=3.1.0
的版本中可用)。例如:
const { loading, error, data } = useQuery(GET_ALL_TODOS, {fetchPolicy: "cache-and-network",nextFetchPolicy: "cache-first",});