首页
/ TanStack Query 架构全景:从一个 monorepo 读懂异步状态管理与多框架适配

TanStack Query 架构全景:从一个 monorepo 读懂异步状态管理与多框架适配

2026-09-05 09:06:20作者:薛曦旖Francesca

TanStack Query(TanStack 查询库)是用于 Web 异步状态管理的开源库,目标是简化服务端状态的获取(fetching)、缓存(caching)、同步(synchronizing)与更新(updating)。本文以仓库根目录的 README.md 为核心骨架,把 README 中列出的四项核心能力逐项落到 packages/ 下的真实源码上,并结合仓库内可直接运行的示例工程与文档站点结构,帮你建立"从 README 的一句话卖点,到 query-core 源码实现,再到 React/Vue/Solid/Svelte/Preact/Lit/Angular 各框架适配"的完整认知,读完后你能快速判断该库适合哪些场景、各框架版本包如何安装、以及如何在本地跑起来验证。

一、README 定义的四项核心能力

README.md 对项目的定位只有一句话:"An async state management library built to simplify fetching, caching, synchronizing, and updating server state."(一个为简化服务端状态获取、缓存、同步与更新而构建的异步状态管理库),并给出四条能力清单:

  • Protocol-agnostic fetching:协议无关的数据获取(REST、GraphQL、Promise 等均可);
  • Caching, refetching, pagination & infinite scroll:缓存、自动重新获取、分页与无限滚动;
  • Mutations, dependent queries & background updates:变更(mutation)、依赖查询与后台刷新;
  • Prefetching, cancellation & React Suspense support:预取、请求取消,以及 React Suspense 支持。

这四条不是营销话术,每一条都能在本仓库的源码与文档中找到对应实现,这也是本文后续各节的展开线索。此外,README 中指向 CONTRIBUTING.md贡献指南 与仓库的包管理器约束(package.jsonpackageManager: pnpm@11.9.0,要求 pnpm ≥ 11.9.0)共同界定了本地开发这套代码的环境前提。

二、monorepo 组织:核心层、框架适配层与周边工具层

pnpm-workspace.yaml 可以看到,仓库把三类目录纳入同一个工作区:packages/*(发布到 npm 的库本体)、integrations/*(针对特定框架版本的回归集成测试工程)、examples/*(各框架的官方示例工程)。这种分层直接对应 README 所描述"一套核心 + 多框架适配"的架构。

2.1 框架无关的核心层:query-core

packages/query-core@tanstack/query-core,当前版本 5.102.8)是所有框架适配包的共享底座,package.json 将其描述为 "The framework agnostic core that powers TanStack Query"。它的公开 API 由 packages/query-core/src/index.ts 统一导出,核心构件包括:

导出 对应源码 职责
QueryClient queryClient.ts 客户端入口,持有 QueryCacheMutationCache,管理默认配置与全局操作
QueryCache / Query queryCache.tsquery.ts 查询缓存与单条查询的完整生命周期
QueryObserver / InfiniteQueryObserver queryObserver.ts 被各框架 hook 订阅的观察者,驱动 UI 更新
MutationCache / Mutation / MutationObserver mutationCache.ts 变更请求的缓存、执行与观察
dehydrate / hydrate hydration.ts 状态序列化/反序列化,支撑 SSR 与持久化
focusManager / onlineManager / environmentManager 同名文件 监听窗口聚焦、网络恢复、环境切换,触发自动重取
notifyManager / retryer / timeoutManager 同名文件 通知调度、重试与取消(CancelledError)、可控的定时器抽象
skipToken utils.ts 条件跳过查询的哨兵值

QueryClient 的构造与挂载逻辑印证了 README 中"background updates(后台刷新)"的实现方式:构造函数默认创建 QueryCacheMutationCachequeryClient.ts#L71-L78),mount() 通过引用计数订阅 focusManageronlineManager——当窗口重新聚焦或网络恢复时,自动 resumePausedMutations() 并调用 #queryCache.onFocus() / onOnline() 触发后台重取(queryClient.ts#L80-L96)。这正是"stale-while-revalidate 式自动缓存刷新"在核心层的落点。

2.2 框架适配层与周边工具层

packages/ 下每个框架适配包都是一层薄封装(各自提供 hook / 响应式 API),共同依赖 query-core;README 强调的"React/Solid/Svelte/Vue Query"在此都有对应包,且版本随仓库同步维护:

npm 包 仓库路径 说明
@tanstack/react-query(5.102.8) packages/react-query React hooks 适配,含 Suspense 支持
@tanstack/solid-query(5.102.8) packages/solid-query Solid 适配
@tanstack/svelte-query(6.1.48) packages/svelte-query Svelte 5 适配
@tanstack/vue-query(5.102.8) packages/vue-query Vue 3 适配(经 vue-demi 兼容 Vue 2)
@tanstack/preact-query(5.102.8) packages/preact-query Preact 适配
@tanstack/lit-query(0.2.20) packages/lit-query Lit 适配器
@tanstack/angular-query-experimental(5.102.8) packages/angular-query-experimental Angular Signals 适配(实验性)

围绕主包还有三类配套工具包:

  • Devtools@tanstack/query-devtools(框架无关面板)以及 @tanstack/react-query-devtools@tanstack/solid-query-devtools@tanstack/svelte-query-devtools@tanstack/preact-query-devtools@tanstack/vue-query-devtools 等框架化面板,用于可视化缓存状态;
  • 持久化@tanstack/query-persist-client-core@tanstack/query-sync-storage-persister@tanstack/query-async-storage-persister,以及各框架的 *-query-persist-client 绑定包,实现缓存跨会话恢复;
  • 开发者工具链@tanstack/eslint-plugin-querypackages/eslint-plugin-query,配套规则文档见 docs/eslint/eslint-plugin-query.md)与 @tanstack/query-codemods(版本迁移 codemods)。

三、README 能力清单的源码印证

3.1 协议无关的数据获取

各框架示例统一把 queryFn 写成"返回 Promise 的普通函数"。以 examples/react/simple/src/index.tsx 为例:

const { isPending, error, data, isFetching } = useQuery({
  queryKey: ['repoData'],
  queryFn: async () => {
    const response = await fetch('https://api.github.com/repos/Tanstack/query')
    return await response.json()
  },
})

queryFn 没有任何协议约束——传 fetch、GraphQL client、甚至 new Promise 都可以,这与 README 第一条能力声明一致。Vue 侧的 examples/vue/simple/src/App.vue 结构完全同构:在 setup() 中调用 useQuery({ queryKey: ['repoData'], queryFn() { ... } }),返回 dataerrorisFetchingisPending 四个响应式状态。

3.2 缓存、重新获取与自动刷新

QueryClient 提供 isFetching(filters)isMutating(filters) 这类按过滤器统计缓存状态的方法(queryClient.ts#L109-L120),底层是 queryCache.findAll / mutationCache.findAll。自动重取由 focusManager(窗口聚焦)、onlineManager(网络恢复)与 QueryClient.mount() 的组合驱动(见第二节),而重试与取消则由 retryer.ts 中的 CancelledError / isCancelledError 支撑 README 所说的"Request Cancellation"。文档侧对应参考:docs/reference/focusManager.mddocs/reference/onlineManager.mddocs/reference/QueryObserver.md

3.3 Mutations 与依赖查询

Mutation / MutationCache / MutationObserver 三件套(mutation.tsmutationCache.tsmutationObserver.ts)构成 README 中"Mutations & dependent queries"的核心:mutation 成功后通常触发 queryClient.invalidateQueries 使相关查询重新获取,实现"变更 → 依赖查询后台更新"的闭环。各框架的完整用法可在 docs/framework/react/guides/ 等框架指南目录中找到(目录内含分页、无限滚动、乐观更新等 30 余篇指南),如 React 参考 API 位于 docs/framework/react/reference/

3.4 预取、取消与 React Suspense

query-core 导出 dehydrate / hydratehydration.ts),把内存缓存序列化为可传输的 JSON,是 SSR 预取的基础设施;@tanstack/react-query-next-experimentalpackages/react-query-next-experimental,"Hydration utils for React Query in the NextJs app directory")则针对 Next.js App Router 提供 hydration 工具。React Suspense 场景的完整示例见 examples/react/suspense/,另有 examples/nextjs-suspense-streaming/ 演示流式场景;Svelte 的 SSR 示例在 examples/svelte/ssr/

四、最小可运行示例:以 React 为例走一遍接入

仓库示例工程 examples/react/simple/ 是最小的端到端接入样板,其 package.json 只依赖 @tanstack/react-query@tanstack/react-query-devtools。完整入口代码(摘自 examples/react/simple/src/index.tsx):

import React from 'react'
import ReactDOM from 'react-dom/client'
import {
  QueryClient,
  QueryClientProvider,
  useQuery,
} from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'

const queryClient = new QueryClient()

export default function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <ReactQueryDevtools />
      <Example />
    </QueryClientProvider>
  )
}

function Example() {
  const { isPending, error, data, isFetching } = useQuery({
    queryKey: ['repoData'],
    queryFn: async () => {
      const response = await fetch(
        'https://api.github.com/repos/Tanstack/query',
      )
      return await response.json()
    },
  })

  if (isPending) return 'Loading...'
  if (error) return 'An error has occurred: ' + error.message
  return (
    <div>
      <h1>{data.full_name}</h1>
      <p>{data.description}</p>
      <div>{isFetching ? 'Updating...' : ''}</div>
    </div>
  )
}

const rootElement = document.getElementById('root')
if (!rootElement) throw new Error('Missing #root element')
ReactDOM.createRoot(rootElement).render(<App />)

这段代码完整呈现了接入三要素:① 创建唯一的 QueryClient 实例;② 用 QueryClientProvider 注入组件树(框架包内部会调用核心层 QueryClient.mount() 建立聚焦/在线监听);③ 组件内用 useQuery 消费 isPending / error / data / isFetching 四态。Vue 版本只需把 hook 换成 @tanstack/vue-queryuseQuery 并放入 setup()(见 examples/vue/simple/src/App.vue),其余语义一致——这就是"核心共享、适配薄化"架构带来的最低学习成本。

五、文档体系与示例、集成测试的分布

README 将读者导向官方文档站;而在本仓库内,文档源文件位于 docs/,与站点结构一一对应,可作为最权威的版本查阅:

除文档外,仓库还有两类高价值资源:

  1. examples/:按框架组织的可运行示例(examples/react/examples/vue/examples/solid/examples/svelte/examples/angular/examples/lit/examples/preact/),覆盖 basicpaginationauto-refetchingoptimistic-updatesssrsuspense 等场景。例如 examples/angular/auto-refetching/ 演示窗口聚焦自动重取,examples/react/load-more-infinite-scroll/ 演示无限滚动(对应 README 第三行能力)。
  2. integrations/:跨框架版本组合的回归集成工程,如 integrations/react-next-14/integrations/react-next-15/integrations/solid-vite/integrations/vue-vite/integrations/svelte-vite/integrations/angular-cli-20/,从文件名可确认其用于校验特定框架大版本下的兼容性。

六、本地开发与验证:pnpm + Nx 工作流

CONTRIBUTING.md 给出开发前置要求:仓库使用 symlink 风格的配置,建议在 Linux/macOS/WSL 下开发;用 corepack 启用 pnpm(版本由 .nvmrcpackage.jsonpnpm@11.9.0 约束)。结合根 package.json 的 scripts 字段,常用命令如下:

目的 命令 说明
安装依赖 pnpm install 工作区含 packages/、integrations/、examples/ 三类目录
构建全部包 pnpm build:all 等价于 nx run-many --target=build,排除 examples/integrations
监听式构建 pnpm run watch nx watch 增量重建,开发期使用
全量测试 pnpm test:ci 串行执行 test:sherif / test:knip / test:docs / test:eslint / test:lib / test:types / test:build / build
仅受影响包测试 pnpm test:pr 基于 nx affected 的增量验证
文档链接校验 pnpm test:docs 执行 scripts/verify-links.ts
包体积检查 pnpm test:size size-limit,保障核心层体积承诺

从源码结构看,测试基建以 Vitest 4 + jsdom 为主(根 package.json 的 devDependencies 中还有多版本 TypeScript 5.6–7.0 别名,用于类型兼容矩阵验证),各包内以 __tests__ / tests 目录组织用例(如 packages/svelte-query/tests/)。

七、参与贡献与生态定位

README.md 的 "Get Involved" 一节与 CONTRIBUTING.md 明确了参与边界:实现类问题与支持性提问请走 GitHub Discussions,issue 仅用于可复现的 bug;PR 需使用模板、聚焦单一变更,且明确允许使用 AI 工具辅助但要求提交者对每处变更负全责,批量提交低质量生成代码会被视为 spam 处理。README 同时列出 TanStack 生态矩阵(Table、Router、Form、Virtual、DB 等)与赞助、合作伙伴入口,说明 Query 是该"headless 数据层"家族中负责异步状态的核心成员。

对使用方的实操建议:以 @tanstack/query-core 理解缓存与观察者模型(第二节表格),按所用框架安装对应适配包与 devtools 包,用 examples/<框架>/simple 作为第一份对照代码跑通最小闭环,再按需进入 docs/framework/<框架>/guides/ 学习分页、预取、持久化等进阶能力。

八、小结

  • 本仓库是 TanStack Query 的 monorepo:packages/query-core 是框架无关核心,各框架包(react/solid/svelte/vue/preact/lit/angular-query 等)是共享核心的薄适配层;
  • README 的四项能力(协议无关获取、缓存与自动重取、mutation 与依赖查询、预取/取消/Suspense)在 queryClient.tsretryer.tshydration.tsfocusManager/onlineManager 中均有可直接核对的实现;
  • 文档源(docs/)、可运行示例(examples/)与集成回归工程(integrations/)三者齐备,配合 pnpm + Nx 工作流(pnpm install && pnpm build:all && pnpm run watch),可以在本地完整复现该库的开发与验证链路。
登录后查看全文
热门项目推荐
相关项目推荐