Apollo Client 4 移除导出全清单:读懂@apollo/client/v4-migration入口点与迁移路线图
【免费下载链接】apollo-clientThe industry-leading GraphQL client for TypeScript, JavaScript, React, Vue, Angular, and more. Apollo Client delivers powerful caching, intuitive APIs, and comprehensive developer tools to accelerate your app development.项目地址: https://gitcode.com/gh_mirrors/ap/apollo-client
导读
Apollo Client 4.0 是一次大版本重构,移除了大量旧 API(HOC、render prop 组件、zen-observable工具、旧错误类型、内部测试工具等)。为了让开发者平滑升级,仓库引入了一个特殊入口点@apollo/client/v4-migration:它是一个类型专用(type-only)入口点,其中每个被移除的导出都被声明为never,并通过 JSDoc 说明移除原因与替代方案。本文以 .api-reports/api-report-v4-migration.api.md 这份 API Report 为骨架,结合 src/v4-migration.ts 源码、3→4 迁移 codemod 与官方迁移指南,系统梳理全部被移除的导出、它们所属的类别以及对应的迁移建议,帮助你理解并完成升级。
v4-migration入口点是什么
一个"报告被移除内容"的特殊模块
在 Apollo Client 4 中,所有在 3.x 中存在、但在 4.0 被移除的公开导出,都被集中到了一个名为@apollo/client/v4-migration的入口点。它的作用不是提供新的功能,而是:
- 让旧代码中的 import 仍然"能解析"(不会直接因为模块不存在而崩溃);
- 让 TypeScript 在任何使用被移除导出的地方报出类型错误;
- 让开发者在报错处悬停即可看到移除原因和迁移建议。
这一点在迁移指南中有明确说明:运行 codemod 后,"所有被移除的导出都移动到了@apollo/client/v4-migration入口点。你应该在使用任何被移除导出之处看到 TypeScript 错误,将鼠标悬停在导出上,即可获得关于该导出为何被移除以及迁移说明的信息"(见 docs/source/migrating/apollo-client-4-migration.mdx 中 "Replace removed exports" 一节)。
实现机制:全部声明为never
从 API Report 可以看到,该入口点中每个导出都被标记为@public @deprecated (undocumented),且类型一律是never。例如:
// @public @deprecated (undocumented) export const ApolloConsumer: never; // @public @deprecated (undocumented) export type BaseQueryOptions = never;never是 TypeScript 的"底部类型",任何变量都无法被赋值为never类型。因此,只要你的代码还引用这些符号,类型检查器就会报错——这正是设计意图:用编译错误强制暴露每一处需要迁移的代码。
在源码 src/v4-migration.ts 中,每个声明都带有完整的 JSDoc,通过{@inheritDoc ...}链接到Removals命名空间下的说明,部分还给出了具体替代方案(详见下文)。package.json中对应导出被映射为:
"./v4-migration": "./src/v4-migration.ts"(见 package.json 的exports字段。)
运行时行为:值型导出会抛错
该入口点是type-only的:类型(type)导出只是占位符,而值(const/class)导出也没有真实实现。迁移指南特别警告:
从
@apollo/client/v4-migration导出的任何运行时值都会在运行时抛错,因为其实现并不存在。
所以它只适合作为迁移期间的过渡锚点,不能作为长期依赖。完成迁移后应删除这些 import。
Removals命名空间:被移除导出的十大类别
src/v4-migration.ts中定义了一个Removals命名空间,把全部移除项归为 10 个类别。API Report 中Removals命名空间的never类型正是这些类别的占位(removedValue、removedType等对应{{name}}模板,由工具展开)。理解这些类别,等于拿到了整份移除清单的分类索引:
| 类别 | 说明 | 典型迁移方向 |
|---|---|---|
HOC | 高阶组件全部移除 | 改用@apollo/client/react导出的 hooks |
renderProp | render prop 组件全部移除 | 改用 hooks |
errors | 错误处理整体重构 | 新的错误类体系(CombinedGraphQLErrors等) |
rxjs | zen-observable实现被替换 | 使用rxjs的操作符与函数 |
implementationDetail | 某 API 的实现细节被移除 | 改用所属公开 API(如HttpLink、BatchLink) |
utility | 不再必要的内部工具 | 多数无替代,直接删除 |
testingLibrary | 测试工具迁移到独立包 | @apollo/graphql-testing-library |
internal | 内部实现不再对外暴露 | 无替代 |
internalTesting | 内部测试工具 | 无替代 |
defer | 特定@defer协议实现 | 可插拔的 incremental handler |
下面按类别逐一展开,并给出源码与迁移指南中对应的替代方案。
HOC 与 render prop 组件:迁移到 hooks
Removals.HOC与Removals.renderProp的说明完全一致:所有高阶组件与 render prop 组件在 4.0 中被移除,"请改用@apollo/client/react包导出的 hooks"。
被移除的值包括:
- HOC:
graphql、withApollo、withMutation、withQuery、withSubscription; - 渲染属性组件:
Query、Mutation、Subscription、ApolloConsumer; - 配套类型:
ChildProps、ChildDataProps、ChildMutateProps、DataProps、DataValue、MutateProps、OptionProps、OperationOption、QueryControls、WithApolloClient、ApolloConsumerProps、QueryComponentOptions、MutationComponentOptions、SubscriptionComponentOptions等。
对应的替代是useQuery、useMutation、useSubscription、useApolloClient等 hooks(React 相关导出统一从@apollo/client/react导入)。顺带说明,@apollo/client/react/parser入口点整体被移除——DocumentType、parser、operationName、verifyDocumentType都属于这一体系(DocumentType的 JSDoc 明确指出它是与parserAPI 一起被移除的实现细节,"mostly an implementation detail … removed without replacement")。
errors:错误处理整体重构
Removals.errors说明:"错误处理已整体重构。"被移除的错误相关导出包括:
- 类:
ApolloError(连同isApolloError判断函数); - 类型:
ApolloErrorOptions、GraphQLErrors、NetworkError、ClientParseError。
4.0 的错误处理变化(详见迁移指南 "New error handling" 一节)可以概括为:
- 统一
error属性:error与errors双属性并存被废弃,所有错误统一挂在error上; - 移除
ApolloError包装:GraphQL 错误改为CombinedGraphQLErrors实例,用CombinedGraphQLErrors.is(error)判断后通过error.errors访问原始错误;协议错误对应CombinedProtocolErrors;网络错误不再包装、原样返回;clientErrors无替代; - 保证 error-like:所有错误都是带
message/name的对象,字符串错误自动包成Error,其他非常规形状被包成UnconventionalError(原对象保存在cause上); - 网络错误遵守
errorPolicy:不再是"永远 throw"; ServerError/ServerParseError成为真正的错误类,可通过各自的.is()静态方法判断。
相关实现可参考 src/errors/CombinedGraphQLErrors.ts、src/errors/CombinedProtocolErrors.ts、src/errors/UnconventionalError.ts 与 src/errors/ServerError.ts。
rxjs:zen-observable时代的工具
Removals.rxjs说明:"Apollo Client 的 Observable 实现已从zen-observable迁移到rxjs。"迁移指南确认rxjs成为 4.0 的新增 peer dependency(安装命令:npm install @apollo/client@latest graphql rxjs)。因此,曾经围绕zen-observable提供的工具全部移除,替换为 rxjs 对应物:
| 被移除导出 | 官方建议替代 |
|---|---|
Concast | rxjs的BehaviorSubject |
ObservableSubscription | rxjs的订阅机制 |
Observer | rxjs的Observer接口 |
asyncMap | rxjs的mergeMap |
fromError | rxjs的throwError |
fromPromise | rxjs的from |
toPromise | rxjs的firstValueFrom/lastValueFrom |
Subscription(@apollo/client/utilities旧工具) | rxjs订阅 |
迁移示例(取自迁移指南):
const observable = fromError(new Error("Oops")); // 旧 const observable = throwError(() => new Error("Oops")); // 新 const promise = toPromise(observable); // 旧 const promise = firstValueFrom(observable); // 新此外,ObservableQuery不再继承自Observable(但仍实现Subscribable与pipe),需要Observable实例的场景请用rxjs的from(observableQuery)转换。
implementationDetail:被并入所属公开 API
Removals.implementationDetail类别下的导出曾是某些核心 API 的内部实现细节,4.0 中不再暴露,其替代通常是所属的公开类或方法:
OperationBatcher(BatchLink的内部实现)→ 直接使用BatchLink(见 src/link/batch/batchLink.ts);RenderPromises(getMarkupFromTree的实现细节)→ 使用 SSR API;addNonReactiveToNamedFragments(内部QueryManager的实现细节)→ 无替代;fixObservableSubclass(ObservableQuery的实现细节)→ 无替代;getFragmentMaskMode、isFullyUnmaskedOperation(data masking 的实现细节)→ 无替代;getInclusionDirectives、Resolver、Resolvers(local state 的实现细节)→ 使用LocalState;getTypenameFromResult(InMemoryCache的实现细节)→ 无替代;isApolloPayloadResult、serializeFetchParameter、throwServerError、transformOperation、validateOperation(HttpLink/ApolloLink.execute的实现细节)→ 其中serializeFetchParameter用JSON.stringify替代、throwServerError改为直接实例化ServerError。
utility:无替代的内部工具
Removals.utility类别下的工具函数是"不再必要的实现细节",全部无替代,直接删除即可。包括:buildQueryFromSelectionSet、canUseAsyncIteratorSymbol、canUseLayoutEffect、canUseSymbol、canUseWeakMap、canUseWeakSet、getDirectiveNames、hasAllDirectives、hasAnyDirectives、hasClientExports、isInlineFragment、isStatefulPromise、removeArgumentsFromDocument、removeClientSetsFromDocument、removeConnectionDirectiveFromDocument、removeFragmentSpreadFromDocument,以及配套类型DirectiveInfo、Directives、GetDirectiveConfig、GetFragmentSpreadConfig、GetNodeConfig、InclusionDirectives、RemoveArgumentsConfig、RemoveDirectiveConfig、RemoveFragmentDefinitionConfig、RemoveFragmentSpreadConfig、RemoveNodeConfig、RemoveVariableDefinitionConfig、TupleToIntersection、UnionToIntersection、VariableValue等。
testingLibrary:迁往独立包
Removals.testingLibrary说明:"测试工具已迁入独立包@apollo/graphql-testing-library。"这主要影响@apollo/client/testing/experimental入口点的createTestSchema、createSchemaFetch,以及测试相关的MockedProvider体系之外的辅助工具。
另外两个测试相关移除在迁移指南中有明确指引:
createMockClient→ "请手动用MockLink创建ApolloClient实例";mockSingleLink→ "它是对MockLink的包装,请直接调用new MockLink(mockedResponses)"。
internal 与 internalTesting:不再对外暴露
Removals.internal:内部导出不再暴露,包括defaultCacheSizes、valueToObjectRepresentation、verifyDocumentType、ObservableQueryFields、OnlyRequiredProperties、PromiseWithState、ReconcilerFunction、MethodKeys、IsStrictlyAny等;Removals.internalTesting:内部测试工具,无替代,包括itAsync、iterateObserversSafely、subscribeAndCount、tick、wait、withErrorSpy、withLogSpy、withWarningSpy。
defer:可插拔的增量交付协议
Removals.defer说明:"该导出属于某个特定@defer协议实现。如今这些实现是可插拔的,该导出未必适用于所有协议规范。"被移除的是isExecutionPatchIncrementalResult、isExecutionPatchInitialResult、isExecutionPatchResult、mergeIncrementalData等增量结果判定/合并工具。
在 4.0 中,增量交付通过incrementalHandler选项按需启用,官方提供Defer20220824Handler(对应 3.x 所支持的旧版规范),见 src/incremental/handlers/defer20220824.ts:
import { Defer20220824Handler } from "@apollo/client/incremental"; new ApolloClient({ // ... incrementalHandler: new Defer20220824Handler(), });迁移指南同时建议创建apollo.d.ts并通过declare module "@apollo/client"扩展TypeOverrides以获得正确的类型推断(Defer20220824Handler.TypeOverrides)。
其他被移除的类型及其去向
除上述类别外,API Report 中还包含一批被移除的类型,迁移指南给出了它们在新版本中的去处:
BaseQueryOptions→ApolloClient.QueryOptions或useQuery.Options;BaseMutationOptions→ApolloClient.MutateOptions或useMutation.Options;FetchMoreQueryOptions→ObservableQuery.FetchMoreOptions;MutationDataOptions→ApolloClient.MutateOptions/useMutation.Options;RefetchQueriesFunction→useMutation.Options['refetchQueries'];DataProxy(命名空间)→ 类型分散在ApolloClient命名空间或Cache命名空间中;PureQueryOptions、FragmentMatcher、MutationUpdaterFn、BatchableRequest、ConcastSourcesArray、ConcastSourcesIterable、SubscriptionCurrentObservable、Masked、MaskedDocumentNode等 → 无直接替代或由新 API 取代(例如Masked/MaskedDocumentNode涉及 data masking 的类型配置变化)。
迁移指南还总结了 4.0 的整体类型变化方向:大部分类型被收纳进所属 API 的命名空间(如ApolloClient.Options、ObservableQuery.Result、useQuery.Options、ApolloLink.Result、MockLink.MockedResponse等),旧类型名虽仍可用但已废弃。此外TContext、TCacheShape、TSerialized三个泛型参数被移除,context 类型改由DefaultContext接口声明合并来扩展。
codemod 如何把导入重定向到v4-migration
3→4 迁移 codemod(源码位于 scripts/codemods/ac3-to-ac4/src,使用说明见 scripts/codemods/ac3-to-ac4/README.md)按固定顺序执行legacyEntrypoints→imports→links→removals→clientSetup。其中removals步骤专门负责将"已被移除的导出"重定向到@apollo/client/v4-migration。
其实现位于 scripts/codemods/ac3-to-ac4/src/removals.ts:内部维护了一张约 150 项的移除清单(removals数组),每一项声明了来源模块、标识符与 import 类型(type或value)。codemod 对每一项调用handleIdentiferRename,把来自@apollo/client、@apollo/client/react、@apollo/client/utilities、@apollo/client/testing等旧入口点的移除导出,统一改写为指向@apollo/client/v4-migration,例如:
import { Concast } from "@apollo/client"; // 旧 import { Concast } from "@apollo/client/v4-migration"; // 新(removals 步骤改写后)该步骤的测试快照 scripts/codemods/ac3-to-ac4/src/tests/snapshots/removals.test.ts.snap 完整记录了改写前后 diff:可以看到ApolloError、DataProxy、fromError、toPromise、Observer、OperationBatcher、graphql、withQuery、parser、mockSingleLink、createMockClient、Concast等大量导出被移除原 import,并新增到@apollo/client/v4-migration的 import 语句中。
运行方式(README 原文):
# 全量执行(按默认顺序) npx @apollo/client-codemod-migrate-3-to-4 --parser ts file1.ts file2.ts # 只执行某个 codemod npx @apollo/client-codemod-migrate-3-to-4 --parser ts file1.ts file2.ts --codemod removals # TS 与 TSX 建议分开执行 npx @apollo/client-codemod-migrate-3-to-4 --parser ts --ignore-pattern="*.{tsx,d.ts}" file1.ts file2.ts npx @apollo/client-codemod-migrate-3-to-4 --parser tsx --ignore-pattern="*.ts" file1.ts file2.ts注意:codemod 不会处理所有破坏性变更(例如setContext→SetContextLink的回调参数顺序反转无法可靠自动化),迁移指南建议通读完整指南后手动处理剩余部分。
如何利用这份 API Report 完成迁移自查
.api-reports/api-report-v4-migration.api.md是 API Extractor 自动生成的包 API 报告(报告头部注明 "Do not edit this file")。对开发者而言,它是一份可检索的移除清单:从中可以快速确认某个符号是否已被移除、它是否值导出(const/class)还是类型导出(type),从而判断迁移动作:
- 确认符号在清单中→ 说明 4.0 已移除,需按上述类别寻找替代;
- 值是
never→ 迁移后运行时调用会抛错,务必删除或替换; - 悬停查看 JSDoc(对应 src/v4-migration.ts 中的 docblock)→ 官方给出的替代方案;
- 运行
removalscodemod→ 自动把所有此类 import 重定向到v4-migration入口点,逐处解决 TypeScript 报错即可。
小结
@apollo/client/v4-migration是 Apollo Client 4.0 为迁移期设计的"移除清单锚点":它以never类型集中占位所有被移除导出,用类型错误驱动你逐一处理,并用 JSDoc 提供替代指引。结合 .api-reports/api-report-v4-migration.api.md(机器可读的全量清单)、src/v4-migration.ts(人类可读的说明)、removals codemod(自动化重定向)以及迁移指南(完整操作步骤),即可系统、可靠地完成从 3.x 到 4.0 的升级:HOC/render prop 换 hooks、Observable 工具换 rxjs、错误处理换新错误类、本地状态接入LocalState、@defer接入incrementalHandler,最终从代码库中彻底清除所有v4-migration引用。
【免费下载链接】apollo-clientThe industry-leading GraphQL client for TypeScript, JavaScript, React, Vue, Angular, and more. Apollo Client delivers powerful caching, intuitive APIs, and comprehensive developer tools to accelerate your app development.项目地址: https://gitcode.com/gh_mirrors/ap/apollo-client
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考