# https://github.com/apollographql/apollo-client 项目说明书

生成时间：2026-07-10 05:49:38 UTC

## 目录

- [核心架构：ApolloClient、Link 与错误处理](#page-1)
- [缓存系统：InMemoryCache 与数据流](#page-2)
- [React 集成：钩子、Suspense 与 SSR](#page-3)
- [扩展性、测试与开发者工具](#page-4)

<a id='page-1'></a>

## 核心架构：ApolloClient、Link 与错误处理

### 相关页面

相关主题：[缓存系统：InMemoryCache 与数据流](#page-2), [React 集成：钩子、Suspense 与 SSR](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/core/ApolloClient.ts](https://github.com/apollographql/apollo-client/blob/main/src/core/ApolloClient.ts)
- [src/core/QueryManager.ts](https://github.com/apollographql/apollo-client/blob/main/src/core/QueryManager.ts)
- [src/core/ObservableQuery.ts](https://github.com/apollographql/apollo-client/blob/main/src/core/ObservableQuery.ts)
- [src/link/core/ApolloLink.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/core/ApolloLink.ts)
- [src/link/core/Link.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/core/Link.ts)
- [src/link/core/Operation.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/core/Operation.ts)
- [src/link/http/HttpLink.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/http/HttpLink.ts)
- [src/link/error/index.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/error/index.ts)
- [src/link/utils/createOperation.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/utils/createOperation.ts)
- [src/errors/index.ts](https://github.com/apollographql/apollo-client/blob/main/src/errors/index.ts)
- [src/cache/core/types/Cache.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/core/types/Cache.ts)
</details>

# 核心架构：ApolloClient、Link 与错误处理

## 1. 总体分层与职责

Apollo Client v4 的核心架构遵循"协调器 + 传输管道 + 缓存"的经典三层模型。`ApolloClient` 作为对外的协调门面，聚合 `cache`、`link` 与 `inMemoryCache` 等子系统，并把 `query`/`mutate`/`subscribe`/`readQuery`/`writeQuery` 等高级 API 委托给内部的 `QueryManager` 执行真正的请求生命周期管理。

- `ApolloClient` 接收构造选项 `ApolloClientOptions`，按需验证 `cache`、`link` 必填，并保留对 `QueryManager` 的强引用 资料来源：[src/core/ApolloClient.ts:120-180]()
- `QueryManager` 维护 `inFlightLinkObservables`、`cache`、`link`、并提供 `query`、`mutate`、`subscribe` 等方法，是状态机式的协调核心 资料来源：[src/core/QueryManager.ts:140-260]()
- `ObservableQuery` 封装单个 GraphQL 操作的订阅语义，把 `nextResult`、`error` 推送给 `useQuery`/`useSubscription` 等 React 集成层 资料来源：[src/core/ObservableQuery.ts:90-200]()

下图展示从用户调用到网络出口的完整数据通路：

```mermaid
flowchart LR
    U[用户调用<br/>client.query / useQuery] --> AC[ApolloClient]
    AC --> QM[QueryManager]
    QM --> OQ[ObservableQuery]
    QM --> C[Cache 读写]
    QM --> L[ApolloLink 链]
    L --> Err[ErrorLink]
    Err --> HL[HttpLink]
    L --> WS[WebSocketLink]
    HL --> N[(GraphQL Server)]
    WS --> N
    N --> C
    C --> OQ
    OQ --> U
```

## 2. ApolloClient 与 QueryManager

`ApolloClient` 在构造时对输入做严格归一化：把 `cache`、`link`、`inMemoryCache` 重新挂到 `this` 上，并把 `defaultOptions`、`devtools` 等挂到 `__cache`/`__devTools` 私有槽位，供 `QueryManager` 读取 资料来源：[src/core/ApolloClient.ts:200-260]()。

`QueryManager` 承担真正的请求调度：

- 使用 `inFlightLinkObservables` 复用对同一 `Operation` 的进行中请求，实现请求去重 资料来源：[src/core/QueryManager.ts:520-560]()
- `query()` 会创建或复用 `ObservableQuery`，通过 `executeQuery` 走 link 链；`mutate()` 走 `executeMutation`；`subscribe()` 走 `executeSubscription` 资料来源：[src/core/QueryManager.ts:640-820]()
- 缓存写入经由 `cache.writeQuery` / `cache.writeFragment`，并对 `@client` 指令做本地化分支处理 资料来源：[src/cache/core/types/Cache.ts:60-120]()

`ObservableQuery` 维护 `latestResult`、`variables`、`observer` 集合，是 React Hook 与命令式 API 之间的桥接层 资料来源：[src/core/ObservableQuery.ts:200-340]()。

## 3. ApolloLink 链与传输扩展

`ApolloLink` 是统一的中间件抽象，定义 `request(operation, forward)` 协议；多个 Link 通过 `ApolloLink.from(links)` 串成链式管道，每一层都能对 `GraphQLRequest` 做改写、转发、拦截或错误处理 资料来源：[src/link/core/ApolloLink.ts:40-90]()。

常用内置 Link：

| Link | 作用 | 关键文件 |
|------|------|---------|
| `HttpLink` | 默认 HTTP 传输，处理 `uri`、`fetch`、`headers`、`credentials` 等 | [src/link/http/HttpLink.ts]() |
| `WebSocketLink` | 封装 `graphql-ws` / `subscriptions-transport-ws`，处理订阅重连与多路复用 | [src/link/ws/index.ts]() |
| `ErrorLink` | 监听 `Observable` 的 `error` 通道与网络异常，调用用户回调 | [src/link/error/index.ts]() |
| `BatchLink` / `RetryLink` | 请求合并、自动重试，配合指数退避 | 社区包 `@apollo/client/link/batch`、`@apollo/client/link/retry` |

请求体构造由 `createOperation` 完成：它把 `GraphQLRequest` 包装成 `Operation`，并填入 `operationName`、`extensions`、`context`、`setContext` 占位 资料来源：[src/link/utils/createOperation.ts:30-90]()。`Operation` 还会包含 `clientAwareness`、`persistedQuery` 等扩展字段，由后续 Link 读取 资料来源：[src/link/core/Operation.ts:50-120]()。

## 4. 错误处理体系

Apollo Client v4 把"协议错误"与"传输错误"统一通过 `Observable` 的 `error` 通道暴露，但通过错误子类区分来源：

- `ApolloError`：所有错误的基类，包含 `graphQLErrors` 与 `networkError` 两个分片 资料来源：[src/errors/index.ts:30-80]()
- `GraphQLError`：来自服务端 `errors` 数组的协议级错误，保留 `path`、`locations`、`extensions`
- `NetworkError`：HTTP/WS 层的传输故障（超时、断连、跨域）
- 涉及订阅写入缓存的失败（例如 `Missing field while writing result`）是社区高频痛点，问题 #8677 显示从 3.3.x 升级后该错误被更严格地抛出 资料来源：[Issue #8677]()

`ErrorLink` 是推荐接入点，它会在 `ApolloLink.from` 链中按位置执行用户提供的 `errorHandler`，可对 `networkError` 做降级、重试或转换为业务异常 资料来源：[src/link/error/index.ts:20-70]()。`HttpLink` 在解析响应时会捕获 `AbortError`、`TypeError` 等底层异常，并包装为 `NetworkError` 抛出 资料来源：[src/link/http/HttpLink.ts:260-340]()。

在 `QueryManager` 内部，`ObservableQuery` 通过 `setError` 触发 `observer.error(...)`，由 React 层 `useQuery` 转换成 `error` 状态与重试回调 资料来源：[src/core/QueryManager.ts:880-940]()

## 5. 实践建议与社区共识

- 永远把 `HttpLink` 放在链路末端，前面叠加重试、鉴权、本地状态、错误等中间件 资料来源：[src/link/core/ApolloLink.ts:60-100]()
- 订阅场景务必将 `WebSocketLink` 与普通查询/变更的 `HttpLink` 组合使用，区分 `operationName` 或 `subscription`/`query` 类型 资料来源：[src/link/ws/index.ts:80-140]()
- 出现协议级错误时优先检查 `extensions.code`（如 `UNAUTHENTICATED`、`PERSISTED_QUERY_NOT_FOUND`），它们是规范化的扩展点 资料来源：[src/errors/index.ts:50-90]()
- 涉及缓存写入的 `Missing field` 警告可通过自定义 `typePolicies.merge` 或 `keyArgs` 调整，问题 #8677 的讨论表明分页/订阅字段是高频触发点 资料来源：[Issue #8677]()
- `client.readQuery`/`readFragment` 历史上对 `optimistic` 标志不敏感，4.2.4 修复后已正确读取乐观结果 资料来源：[Release @apollo/client@4.2.4]()

## 6. 小结

`ApolloClient` + `QueryManager` + `ApolloLink` 构成 v4 版本的协调骨架：`ApolloClient` 暴露简洁 API，`QueryManager` 负责状态与去重，`ApolloLink` 把传输和中间件解耦。错误处理贯穿整条链路——从 `HttpLink`/`WebSocketLink` 抛出的 `NetworkError`、到服务端返回的 `GraphQLError`，最终在 `ObservableQuery` 汇聚为统一的 `ApolloError` 推送给 UI 层。理解这条主链路，是编写自定义 Link、调试缓存一致性以及排查订阅错误的前提。

---

<a id='page-2'></a>

## 缓存系统：InMemoryCache 与数据流

### 相关页面

相关主题：[核心架构：ApolloClient、Link 与错误处理](#page-1), [React 集成：钩子、Suspense 与 SSR](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/cache/inmemory/inMemoryCache.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/inmemory/inMemoryCache.ts)
- [src/cache/inmemory/entityStore.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/inmemory/entityStore.ts)
- [src/cache/inmemory/policies.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/inmemory/policies.ts)
- [src/cache/inmemory/readFromStore.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/inmemory/readFromStore.ts)
- [src/cache/inmemory/writeToStore.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/inmemory/writeToStore.ts)
- [src/cache/inmemory/reactiveVars.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/inmemory/reactiveVars.ts)
</details>

# 缓存系统：InMemoryCache 与数据流

## 概述

Apollo Client 的 `InMemoryCache` 是框架默认的规范化（normalized）缓存实现，位于 `src/cache/inmemory/` 目录下。它将服务器返回的 GraphQL 响应按照类型与字段规则拆分为「实体（entity）」存入扁平存储，使得同一实体在不同查询之间可被复用与共享。`InMemoryCache` 实现了通用的 `Cache` 接口，通过 `client.cache` 暴露给用户，并配合 `ApolloClient` 完成查询、变更、订阅的数据回写与读取。

社区中常见的痛点（例如 #8677 订阅写入时 `Missing field while writing result` 错误、#13304 关于 `@stream` 指令在写路径上的开销问题）大多源自 `StoreWriter.processSelectionSet` 与规范化逻辑中的边界行为。

资料来源：[src/cache/inmemory/inMemoryCache.ts:1-40]()

## 核心组件

`InMemoryCache` 内部主要由五个协作模块组成：

| 模块 | 文件 | 职责 |
| --- | --- | --- |
| `InMemoryCache` | `inMemoryCache.ts` | 缓存入口，组装读取/写入、策略与广播 |
| `EntityStore` | `entityStore.ts` | 扁平化存储 `StoreObject`，按 `EntityStore.Root` 分组 |
| `Policies` | `policies.ts` | 类型策略 `TypePolicies`，提供 `keyFn`、`merge` 行为 |
| `StoreWriter` | `writeToStore.ts` | 把响应数据写入 `EntityStore`，处理合并与字段策略 |
| `StoreReader` | `readFromStore.ts` | 从 `EntityStore` 反规范化出查询所需结构 |
| `ReactiveVars` | `reactiveVars.ts` | 独立于规范化数据的本地响应式变量 |

`InMemoryCache` 通过 `addOptimistic` / `removeOptimistic` 提供乐观更新能力，并通过 `broadcastWatches` 在写入后通知所有 `QueryInfo` 重新执行，从而驱动 UI 更新。

资料来源：[src/cache/inmemory/inMemoryCache.ts:60-160](), [src/cache/inmemory/entityStore.ts:1-60]()

## 写入流：GraphQL 响应 → 规范化存储

写路径由 `StoreWriter` 主导。当一个查询/变更/订阅的响应到达客户端时，`InMemoryCache.write` 会调用 `StoreWriter.processSelectionSet`，递归遍历 selection set，按 `policies` 中配置的字段策略生成实体标识符并写入 `EntityStore`：

```mermaid
flowchart LR
  A[QueryInfo / Mutation Result] --> B[InMemoryCache.write]
  B --> C[StoreWriter.processSelectionSet]
  C --> D{字段有 merge 函数?}
  D -- 是 --> E[调用 merge 函数]
  D -- 否 --> F[按 keyFn 写入 EntityStore]
  E --> G[EntityStore.merge]
  F --> G
  G --> H[broadcastWatches]
  H --> I[触发依赖该字段的 Observer]
```

关键步骤：

1. **归一化键生成**：对每个 `Selection` 调用 `getStoreFieldName`，并依据 `policies` 中的 `keyArgs` 把参数序列化进实体 ID。资料来源：[src/cache/inmemory/writeToStore.ts:120-200]()
2. **合并行为**：若字段声明了 `merge`（例如分页列表），`StoreWriter` 把传入的子字段作为补丁传入合并函数；否则整字段被替换。资料来源：[src/cache/inmemory/writeToStore.ts:260-340]()
3. **写入存储**：`EntityStore.merge` 在 `StoreObject` 层面覆盖或合并字段；所有写入都通过 `this.data.merge` 走内部锁机制以保证事务安全。资料来源：[src/cache/inmemory/entityStore.ts:80-150]()
4. **广播变更**：写入完成后调用 `cache.broadcastWatches`，所有依赖受影响字段的 `QueryInfo` 会重新执行 `cache.diff` 并把结果推送给 React `useQuery` 等订阅者。

社区讨论的 #13304 指出，自 `@stream` 支持引入以来，`hasDirectives(["stream"])` 在每个无 `merge` 函数的字段上都会被求值，即便应用从不使用 `@stream`。这意味着开发者若想降低写路径开销，需要在自定义 `TypePolicies` 中显式提供 `merge` 或避免对带指令的字段使用默认写路径。

## 读取流：缓存命中 → 反规范化

读取由 `StoreReader` 完成。`InMemoryCache.diff` 在每次 `useQuery` 渲染、变更回调等场景触发，最终调用 `StoreReader.readField` 与 `StoreReader.executeSelectionSet`：

1. 从 `optimisticData` 或 `data` 选定的 `EntityStore` 中，按 `StoreObject` 取出字段；
2. 若字段引用另一实体（例如 `User`），递归读取并在 `EntityStore.Root["__ref"]` 表中拼接 ID；
3. 调用字段策略中的 `read` 函数（如果存在），允许对字段进行投影、过滤或默认值补齐；
4. 对分页字段使用 `read` / `merge` 协同，将内部存储结构还原为客户端期望的数组形态。资料来源：[src/cache/inmemory/readFromStore.ts:30-110](), [src/cache/inmemory/policies.ts:40-120]()

读取时 `InMemoryCache` 会构造一个 `DiffInfo`，通过 `broadcastWatches` 复用同一份结果，避免重复计算。

## 类型策略与响应式变量

`policies.ts` 暴露的 `TypePolicies` 是 InMemoryCache 的扩展点，允许用户自定义：

- `keyFields`：决定实体归一化键；
- `keyArgs`：决定列表/字段参数如何影响缓存键（@apollo/client@4.2.5 起 `KeyArgsFunction` 与 `RelayFieldPolicy` 已导出，便于用户实现分页与 Relay 风格合并）；
- `merge`：定义合并逻辑（如无限滚动、Reley 全局 ID）；
- `read`：在读取时对实体进行加工。

`ReactiveVars` 提供一种不进入 `EntityStore`、直接通知订阅者的本地状态原语，常用于主题、过滤器等场景。`makeVar(initial)` 返回一个 `ReactiveVar<T>`，调用 `var(newValue)` 会触发缓存的 `broadcastWatches`。资料来源：[src/cache/inmemory/reactiveVars.ts:30-90]()

## 进阶：乐观更新与 GC

`InMemoryCache` 维护两层数据：已落库的真实数据 `data`，以及在变更确认前可被替换的 `optimistic`。乐观更新通过 `cache.recordOptimisticTransaction` 进入事务，调用 `removeOptimistic(id)` 时回滚。资料来源：[src/cache/inmemory/inMemoryCache.ts:200-280]()

`EntityStore` 内置引用计数 GC：每次写入后调用 `gc()` 找出无引用（被 `ROOT_QUERY` / `ROOT_MUTATION` 等根间接引用）的实体并清理，可在 `InMemoryCache` 构造选项中按需调用。资料来源：[src/cache/inmemory/entityStore.ts:200-260]()

通过这套「写入规范化—读取反规范化—类型策略扩展—响应式广播」的数据流，`InMemoryCache` 提供了 GraphQL 客户端所需的去重、复用与即时更新能力，也是 Apollo Client 4.x 缓存可扩展性（#13250 中新增的 `client.cache` 类型注入）的核心基础。

---

<a id='page-3'></a>

## React 集成：钩子、Suspense 与 SSR

### 相关页面

相关主题：[核心架构：ApolloClient、Link 与错误处理](#page-1), [扩展性、测试与开发者工具](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/react/context/ApolloProvider.tsx](https://github.com/apollographql/apollo-client/blob/main/src/react/context/ApolloProvider.tsx)
- [src/react/hooks/useQuery.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/hooks/useQuery.ts)
- [src/react/hooks/useSuspenseQuery.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/hooks/useSuspenseQuery.ts)
- [src/react/hooks/useBackgroundQuery.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/hooks/useBackgroundQuery.ts)
- [src/react/hooks/useFragment.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/hooks/useFragment.ts)
- [src/react/hooks/useMutation.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/hooks/useMutation.ts)
- [src/react/hooks/useSubscription.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/hooks/useSubscription.ts)
- [src/react/ssr/RenderPromises.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/ssr/RenderPromises.ts)
- [src/react/ssr/client.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/ssr/client.ts)
- [src/react/queryPreloader.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/queryPreloader.ts)
</details>

# React 集成：钩子、Suspense 与 SSR

## 概述与作用范围

Apollo Client 的 React 集成层为使用 GraphQL 的 React 应用提供了完整的 UI 数据绑定机制。它将底层的 `ApolloClient` 实例与 React 的渲染模型、Suspense 边界以及服务器端渲染（SSR）流式输出整合起来，通过上下文（Context）与钩子（Hooks）让组件能够声明式地消费查询、变更和订阅。该层既是 `ApolloClient` 与 React 之间的桥梁，也是处理并发渲染与 SSR 提取的关键模块。

社区长期关注的 [RFC: React 18 SSR + Suspense Support（#10231）](https://github.com/apollographql/apollo-client/issues/10231) 最终落地的能力（包括 `useSuspenseQuery`、查询预加载以及流式 SSR）正是该集成层所提供的核心功能。

## ApolloProvider 与上下文分发

`ApolloProvider` 是整个 React 集成的入口组件。它接收一个 `client: ApolloClient<any>` 实例，并通过 React Context 将其下发至组件树。`ApolloProvider` 还会自动执行 `client.connect()` 与 `client.disconnect()`，从而在挂载时建立与缓存的连接、在卸载时关闭底层订阅，避免内存泄漏。

资料来源：[src/react/context/ApolloProvider.tsx:18-63]()

```tsx
import { ApolloProvider } from "@apollo/client";

<ApolloProvider client={client}>
  <App />
</ApolloProvider>
```

由于所有钩子内部均通过 `useContext(ApolloContext)` 读取客户端，因此在使用任何 `useQuery`、`useSuspenseQuery` 等钩子之前，必须由 `ApolloProvider` 注入客户端实例。`ApolloProvider` 自身还可接收自定义的 `context` 属性，便于多客户端共存场景下使用独立 Context，避免交叉读取。

## 主要数据钩子

### `useQuery`：传统订阅式查询

`useQuery` 是最常用的查询钩子，它基于 `ObservableQuery` 在组件挂载时发起请求，并将 `loading`、`data`、`error`、`previousData` 等状态通过 `useReducer` 与 `useState` 暴露给组件。它支持 `variables`、`skip`、`pollInterval`、`fetchPolicy` 等参数，并可通过 `notifyOnNetworkStatusChange` 控制渲染节奏。

资料来源：[src/react/hooks/useQuery.ts:1-120]()

```tsx
const { data, loading, error } = useQuery(GET_USER, {
  variables: { id },
  skip: !id,
});
```

对于订阅场景，`useSubscription` 与 `useMutation` 也采用类似模式：分别包装 `Observable.subscribe` 与 `MutationStore` 中的变更流程，并通过 `onCompleted`、`onError` 等回调反馈结果。`useFragment` 则聚焦于缓存片段订阅，使用 `useSyncExternalStore` 在数据变更时强制重渲染。

资料来源：[src/react/hooks/useSubscription.ts:1-80]()
资料来源：[src/react/hooks/useMutation.ts:1-90]()
资料来源：[src/react/hooks/useFragment.ts:1-80]()

### `useSuspenseQuery`：Suspense 集成查询

`useSuspenseQuery` 提供了对 React Suspense 的原生支持。当数据尚未就绪时，钩子会抛出一个 `Promise`，让最近的 Suspense 边界捕获并渲染 fallback；数据返回后，组件重新渲染即可获得完整结果。这一设计消除了 `loading` 状态判断，使组件代码更加声明式。

资料来源：[src/react/hooks/useSuspenseQuery.ts:1-150]()

```tsx
import { useSuspenseQuery } from "@apollo/client";

const { data } = useSuspenseQuery(GET_USER, { variables: { id } });
```

与 `useQuery` 不同，`useSuspenseQuery` 不返回 `loading` 字段，因此错误必须通过配套的 `useSuspenseQuery` 边界或在父级 Suspense 之外通过 ErrorBoundary 处理。其返回结构包含 `data`、`error`（若发生错误）、`variables` 等。

### `useBackgroundQuery` 与查询预加载

`useBackgroundQuery` 用于在渲染前预先发起请求。常见用法是在路由切换或交互前通过 `useBackgroundQuery` 提前触发数据获取，再在子组件中通过 `useReadQuery` 同步读取结果，从而消除渲染期等待。`queryPreloader.ts` 实现了底层的 `createQueryPreloader` 函数，允许脱离 React 生命周期进行预加载（如在事件处理函数中）。

资料来源：[src/react/hooks/useBackgroundQuery.ts:1-100]()
资料来源：[src/react/queryPreloader.ts:1-80]()

```tsx
const [queryRef] = useBackgroundQuery(GET_USER, { variables: { id } });
const { data } = useReadQuery(queryRef);
```

## 服务器端渲染（SSR）支持

Apollo Client 在 SSR 场景下提供两类集成方式，分别对应传统 React 17 与 React 18 流式渲染。

### `RenderPromises`：等待所有在渲期间发起的查询

`RenderPromises` 通过一个全局 Map 收集组件在 `renderToString` 过程中通过钩子发起的请求，并在渲染结束后统一调用其 `resolve` 完成。`renderToStringWithData` 工具函数会遍历该 Map，等待所有 Promise 完成，确保生成的 HTML 中包含完整数据。

资料来源：[src/react/ssr/RenderPromises.ts:1-120]()

```ts
import { renderToStringWithData } from "@apollo/client/react/ssr";

const html = await renderToStringWithData(app);
```

### React 18 流式 SSR

对于 `renderToPipeableStream` 与 `renderToReadableStream`，集成层通过 `RenderPromises` 注册的 `abort` 与 `done` 回调与 React 的流控制协作，使得 Suspense 边界可以在数据到达时分批输出 HTML，实现“边获取边发送”的效果。这一能力正是社区 #10231 提议的最终实现形态。

资料来源：[src/react/ssr/client.ts:1-60]()

## 数据流概览

下表概括了关键钩子的运行时行为差异：

| 钩子 | 返回 `loading` | 抛 Promise（Suspense） | 适用场景 |
|------|----------------|------------------------|----------|
| `useQuery` | 是 | 否 | 传统 UI、需手动 loading 状态 |
| `useSuspenseQuery` | 否 | 是 | 配合 `<Suspense>` 与 ErrorBoundary |
| `useBackgroundQuery` | — | 是 | 预加载、跨组件复用 |
| `useFragment` | 否 | 否 | 缓存片段订阅 |
| `useSubscription` | — | 否 | 实时数据流 |
| `useMutation` | 是 | 否 | 表单提交与变更 |

资料来源：[src/react/hooks/useQuery.ts:30-90]()
资料来源：[src/react/hooks/useSuspenseQuery.ts:40-120]()
资料来源：[src/react/hooks/useBackgroundQuery.ts:20-70]()

## 关键注意事项

- **必须包裹在 `ApolloProvider` 中**：所有钩子都依赖 `ApolloContext`。
- **`useSuspenseQuery` 的错误处理**：错误会向上传递至 ErrorBoundary，不会出现在返回值中。
- **SSR 时使用 `InMemoryCache` 的 `restore`**：避免服务端与客户端缓存水合不一致。
- **多客户端场景**：通过 `ApolloProvider` 的 `context` 属性传入独立的 React Context，避免冲突。
- **`useFragment` 与严格模式**：`useSyncExternalStore` 保证在并发模式下不撕裂 UI。

通过上述组件与钩子的组合，Apollo Client 为 React 应用提供了从简单查询到并发 Suspense、再到流式 SSR 的完整数据流方案。

---

<a id='page-4'></a>

## 扩展性、测试与开发者工具

### 相关页面

相关主题：[核心架构：ApolloClient、Link 与错误处理](#page-1), [缓存系统：InMemoryCache 与数据流](#page-2), [React 集成：钩子、Suspense 与 SSR](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/local-state/LocalState.ts](https://github.com/apollographql/apollo-client/blob/main/src/local-state/LocalState.ts)
- [src/masking/index.ts](https://github.com/apollographql/apollo-client/blob/main/src/masking/index.ts)
- [src/incremental/handlers/defer20220824.ts](https://github.com/apollographql/apollo-client/blob/main/src/incremental/handlers/defer20220824.ts)
- [src/testing/react/MockedProvider.tsx](https://github.com/apollographql/apollo-client/blob/main/src/testing/react/MockedProvider.tsx)
- [src/testing/core/mocking/mockLink.ts](https://github.com/apollographql/apollo-client/blob/main/src/testing/core/mocking/mockLink.ts)
- [src/testing/matchers/index.ts](https://github.com/apollographql/apollo-client/blob/main/src/testing/matchers/index.ts)
- [src/cache/inmemory/writeToStore.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/inmemory/writeToStore.ts)
- [src/core/Scalar.ts](https://github.com/apollographql/apollo-client/blob/main/src/core/Scalar.ts)
- [src/cache/inmemory/policies.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/inmemory/policies.ts)
</details>

# 扩展性、测试与开发者工具

本页覆盖 Apollo Client 在 4.x 阶段的三类支撑能力：**扩展点**（本地状态、缓存策略、协议级增量、字段屏蔽）、**测试栈**（MockedProvider、mockLink、Jest 匹配器）、**开发者工具**（Codegen 集成、公共类型导出）。

## 1. 客户端可扩展机制

### 1.1 本地状态 (Local State)
`LocalState` 是处理 `@client` 指令的入口，它在把响应回写到调用方之前，合并本地 `resolvers` 计算的字段，并负责本地 Fragment 的注册与查询重写，使得本地选择集无需访问远端即可被满足。

资料来源：[src/local-state/LocalState.ts:1-120]()

### 1.2 缓存字段策略
`InMemoryCache.typePolicies` 接受字段级策略对象，包含 `keyArgs`、`read`、`merge` 等钩子。底层 `policies.ts` 暴露 `KeyArgsFunction` 与 `RelayFieldPolicy` 两类关键类型，自 `@apollo/client@4.2.5` 起被纳入公共入口，类型系统对分页与归一化键的支持变得更加直接。

资料来源：[src/cache/inmemory/policies.ts:1-80]()

### 1.3 自定义 Scalar
`Scalar` 类承载序列化与校验逻辑，新增的 `Scalar.fromGraphQLScalarType` 帮助从 `graphql` 包导出的 `GraphQLScalarType` 一键转换成 Apollo 的 `Scalar`，用来对接 `graphql` v17+ 的对等依赖。

资料来源：[src/core/Scalar.ts:1-60]()

## 2. 协议级能力增量

### 2.1 @defer / @stream 增量交付
`defer20220824.ts` 按 2022-08 规范解析增量分片：每个 `incremental` payload 被路由至缓存写入管线，再触发订阅监听器。注意，`@stream` 标识的字段会在 `writeToStore.ts` 中触发 `hasDirectives(["stream"])` 分支，社区反馈 (#13304) 该判断被无条件求值，对不使用 `@stream` 的应用带来可观开销。

资料来源：[src/incremental/handlers/defer20220824.ts:1-100]()
资料来源：[src/cache/inmemory/writeToStore.ts:1-200]()

### 2.2 字段屏蔽 (Masking)
`masking/index.ts` 实现 `@mask` 与 `@unmask` 两条指令：被屏蔽的字段值会被替换为规范化引用，避免把真实数据写入缓存；常见于权限分级或隐私合规场景。

资料来源：[src/masking/index.ts:1-80]()

## 3. 测试与模拟

### 3.1 测试栈分层
```mermaid
flowchart TB
    A[被测组件] --> B[MockedProvider]
    B --> C[ApolloProvider]
    B --> D[mockLink]
    D --> E[Schema/Resolvers/Mocks]
    E --> F[Response]
```
`MockedProvider` 接收 `mocks`、`addTypename` 等配置，内部装配 `ApolloProvider` 和基于 `mockLink` 的链路；`mockLink` 按操作名或变量集合进行匹配，再依次派发 mock 结果。这种分层让单元测试可以复用生产环境的 `ApolloProvider`，同时绕过真实网络。

资料来源：[src/testing/react/MockedProvider.tsx:1-150]()
资料来源：[src/testing/core/mocking/mockLink.ts:1-150]()

### 3.2 Jest 匹配器
`testing/matchers/index.ts` 暴露 `toHaveBeenCalled`、`mockedSnapshot` 等匹配器，让 GraphQL 测试断言沿用 Jest 风格。社区反馈 (issue #5917) 指出：当 MockedProvider 没有匹配到任何 mock 时缺少可观测的诊断信号，这些匹配器在补足断言可读性方面扮演关键角色。

资料来源：[src/testing/matchers/index.ts:1-60]()

## 4. 开发者工具集成

### 4.1 GraphQL Codegen 插件
官方维护的 `@apollo/client-graphql-codegen` 插件可为类型化操作生成 `useQuery`/`useMutation` 包装。自 `2.1.0` 起兼容最新 GraphQL Codegen 主版本，`2.1.1` 修复了误剔除运行时文件的问题，让发布的 npm 包具备完整的钩子函数入口。

### 4.2 类型公共导出
`KeyArgsFunction`、`RelayFieldPolicy` 等已经升级为主入口导出，而 `@apollo/client@4.3.0-alpha.0` 起 `client.cache` 允许显式声明自定义缓存实现，使缓存实现可以被替换或包装，从而为 SSR、持久化等场景打开扩展空间。

## 总结
Apollo Client 在 4.x 阶段持续降低扩展门槛：既通过 `Scalar.fromGraphQLScalarType` 与公共类型导出强化强类型体验，又通过 Codegen 与测试栈提供端到端 DX，同时借助 `@defer/@stream` 与 `@mask` 把新协议与合规能力下沉到客户端运行时。理解这些扩展点，有助于在大型应用中按需定制缓存、网络与渲染语义。

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：apollographql/apollo-client

摘要：发现 25 个潜在踩坑项，其中 3 个为 high/blocking；最高优先级：安装坑 - 来源证据：Incomplete cache diffs eagerly build missing-field diagnostics (JSON.stringify of store objects + MissingFieldError con…。

## 1. 安装坑 · 来源证据：Incomplete cache diffs eagerly build missing-field diagnostics (JSON.stringify of store objects + MissingFieldError con…

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：Incomplete cache diffs eagerly build missing-field diagnostics (JSON.stringify of store objects + MissingFieldError construction) in production
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/apollographql/apollo-client/issues/13305 | 来源类型 github_issue 暴露的待验证使用条件。

## 2. 配置坑 · 来源证据：RFC: Custom scalars

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个配置相关的待验证问题：RFC: Custom scalars
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/apollographql/apollo-client/issues/13227 | 来源讨论提到 node 相关条件，需在安装/试用前复核。

## 3. 安全/权限坑 · 来源证据：Dependency Dashboard

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：Dependency Dashboard
- 对用户的影响：可能影响升级、迁移或版本选择。
- 证据：community_evidence:github | https://github.com/apollographql/apollo-client/issues/11062 | 来源讨论提到 node 相关条件，需在安装/试用前复核。

## 4. 身份坑 · 仓库名和安装名不一致

- 严重度：medium
- 证据强度：runtime_trace
- 发现：仓库名 `apollo-client` 与安装入口 `@apollo/client` 不完全一致。
- 对用户的影响：用户照着仓库名搜索包或照着包名找仓库时容易走错入口。
- 复现命令：`npm install @apollo/client`
- 证据：identity.distribution | https://github.com/apollographql/apollo-client | repo=apollo-client; install=@apollo/client

## 5. 安装坑 · 失败模式：installation: @apollo/client@4.2.3

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: @apollo/client@4.2.3
- 对用户的影响：Upgrade or migration may change expected behavior: @apollo/client@4.2.3
- 证据：failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.2.3 | @apollo/client@4.2.3

## 6. 安装坑 · 失败模式：installation: Dependency Dashboard

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: Dependency Dashboard
- 对用户的影响：Developers may fail before the first successful local run: Dependency Dashboard
- 证据：failure_mode_cluster:github_issue | https://github.com/apollographql/apollo-client/issues/11062 | Dependency Dashboard, failure_mode_cluster:github_issue | https://github.com/apollographql/apollo-client/issues/11062 | Dependency Dashboard

## 7. 安装坑 · 来源证据：Cache writes call hasDirectives(["stream"]) for every written field — large overhead for apps that never use @stream

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：Cache writes call hasDirectives(["stream"]) for every written field — large overhead for apps that never use @stream
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/apollographql/apollo-client/issues/13304 | 来源讨论提到 node 相关条件，需在安装/试用前复核。

## 8. 配置坑 · 失败模式：configuration: @apollo/client@4.3.0-alpha.2

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this configuration risk before relying on the project: @apollo/client@4.3.0-alpha.2
- 对用户的影响：Upgrade or migration may change expected behavior: @apollo/client@4.3.0-alpha.2
- 证据：failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.3.0-alpha.2 | @apollo/client@4.3.0-alpha.2

## 9. 配置坑 · 失败模式：configuration: RFC: Custom scalars

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this configuration risk before relying on the project: RFC: Custom scalars
- 对用户的影响：Developers may misconfigure credentials, environment, or host setup: RFC: Custom scalars
- 证据：failure_mode_cluster:github_issue | https://github.com/apollographql/apollo-client/issues/13227 | RFC: Custom scalars

## 10. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 证据：capability.assumptions | https://github.com/apollographql/apollo-client | README/documentation is current enough for a first validation pass.

## 11. 运行坑 · 失败模式：runtime: @apollo/client-graphql-codegen@2.1.1

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this runtime risk before relying on the project: @apollo/client-graphql-codegen@2.1.1
- 对用户的影响：Upgrade or migration may change expected behavior: @apollo/client-graphql-codegen@2.1.1
- 证据：failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client-graphql-codegen%402.1.1 | @apollo/client-graphql-codegen@2.1.1

## 12. 维护坑 · 失败模式：migration: @apollo/client@4.3.0-alpha.1

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this migration risk before relying on the project: @apollo/client@4.3.0-alpha.1
- 对用户的影响：Upgrade or migration may change expected behavior: @apollo/client@4.3.0-alpha.1
- 证据：failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.3.0-alpha.1 | @apollo/client@4.3.0-alpha.1

## 13. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | https://github.com/apollographql/apollo-client | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://github.com/apollographql/apollo-client | no_demo; severity=medium

## 15. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 证据：risks.scoring_risks | https://github.com/apollographql/apollo-client | no_demo; severity=medium

## 16. 运行坑 · 失败模式：performance: @apollo/client@4.3.0-alpha.0

- 严重度：low
- 证据强度：source_linked
- 发现：Developers should check this performance risk before relying on the project: @apollo/client@4.3.0-alpha.0
- 对用户的影响：Upgrade or migration may change expected behavior: @apollo/client@4.3.0-alpha.0
- 证据：failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.3.0-alpha.0 | @apollo/client@4.3.0-alpha.0

## 17. 运行坑 · 失败模式：performance: Cache writes call hasDirectives(["stream"]) for every written field — large overhead for apps...

- 严重度：low
- 证据强度：source_linked
- 发现：Developers should check this performance risk before relying on the project: Cache writes call hasDirectives(["stream"]) for every written field — large overhead for apps that never use @stream
- 对用户的影响：Developers may hit a documented source-backed failure mode: Cache writes call hasDirectives(["stream"]) for every written field — large overhead for apps that never use @stream
- 证据：failure_mode_cluster:github_issue | https://github.com/apollographql/apollo-client/issues/13304 | Cache writes call hasDirectives(["stream"]) for every written field — large overhead for apps that never use @stream

## 18. 运行坑 · 失败模式：performance: Incomplete cache diffs eagerly build missing-field diagnostics (JSON.stringify of store objec...

- 严重度：low
- 证据强度：source_linked
- 发现：Developers should check this performance risk before relying on the project: Incomplete cache diffs eagerly build missing-field diagnostics (JSON.stringify of store objects + MissingFieldError construction) in production
- 对用户的影响：Developers may hit a documented source-backed failure mode: Incomplete cache diffs eagerly build missing-field diagnostics (JSON.stringify of store objects + MissingFieldError construction) in production
- 证据：failure_mode_cluster:github_issue | https://github.com/apollographql/apollo-client/issues/13305 | Incomplete cache diffs eagerly build missing-field diagnostics (JSON.stringify of store objects + MissingFieldError construction) in production

## 19. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 证据：evidence.maintainer_signals | https://github.com/apollographql/apollo-client | issue_or_pr_quality=unknown

## 20. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 证据：evidence.maintainer_signals | https://github.com/apollographql/apollo-client | release_recency=unknown

## 21. 维护坑 · 失败模式：maintenance: @apollo/client-graphql-codegen@2.1.0

- 严重度：low
- 证据强度：source_linked
- 发现：Developers should check this maintenance risk before relying on the project: @apollo/client-graphql-codegen@2.1.0
- 对用户的影响：Upgrade or migration may change expected behavior: @apollo/client-graphql-codegen@2.1.0
- 证据：failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client-graphql-codegen%402.1.0 | @apollo/client-graphql-codegen@2.1.0

## 22. 维护坑 · 失败模式：maintenance: @apollo/client@4.2.2

- 严重度：low
- 证据强度：source_linked
- 发现：Developers should check this maintenance risk before relying on the project: @apollo/client@4.2.2
- 对用户的影响：Upgrade or migration may change expected behavior: @apollo/client@4.2.2
- 证据：failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.2.2 | @apollo/client@4.2.2

## 23. 维护坑 · 失败模式：maintenance: @apollo/client@4.2.4

- 严重度：low
- 证据强度：source_linked
- 发现：Developers should check this maintenance risk before relying on the project: @apollo/client@4.2.4
- 对用户的影响：Upgrade or migration may change expected behavior: @apollo/client@4.2.4
- 证据：failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.2.4 | @apollo/client@4.2.4

## 24. 维护坑 · 失败模式：maintenance: @apollo/client@4.2.5

- 严重度：low
- 证据强度：source_linked
- 发现：Developers should check this maintenance risk before relying on the project: @apollo/client@4.2.5
- 对用户的影响：Upgrade or migration may change expected behavior: @apollo/client@4.2.5
- 证据：failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.2.5 | @apollo/client@4.2.5

## 25. 维护坑 · 失败模式：maintenance: @apollo/client@4.2.6

- 严重度：low
- 证据强度：source_linked
- 发现：Developers should check this maintenance risk before relying on the project: @apollo/client@4.2.6
- 对用户的影响：Upgrade or migration may change expected behavior: @apollo/client@4.2.6
- 证据：failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.2.6 | @apollo/client@4.2.6

<!-- canonical_name: apollographql/apollo-client; human_manual_source: deepwiki_human_wiki -->
