TanStack Query 架构全景:从一个 monorepo 读懂异步状态管理与多框架适配
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.json 中 packageManager: 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 | 客户端入口,持有 QueryCache 与 MutationCache,管理默认配置与全局操作 |
QueryCache / Query |
queryCache.ts、query.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(后台刷新)"的实现方式:构造函数默认创建 QueryCache 与 MutationCache(queryClient.ts#L71-L78),mount() 通过引用计数订阅 focusManager 与 onlineManager——当窗口重新聚焦或网络恢复时,自动 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-query(packages/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() { ... } }),返回 data、error、isFetching、isPending 四个响应式状态。
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.md、docs/reference/onlineManager.md、docs/reference/QueryObserver.md。
3.3 Mutations 与依赖查询
Mutation / MutationCache / MutationObserver 三件套(mutation.ts、mutationCache.ts、mutationObserver.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 / hydrate(hydration.ts),把内存缓存序列化为可传输的 JSON,是 SSR 预取的基础设施;@tanstack/react-query-next-experimental(packages/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-query 的 useQuery 并放入 setup()(见 examples/vue/simple/src/App.vue),其余语义一致——这就是"核心共享、适配薄化"架构带来的最低学习成本。
五、文档体系与示例、集成测试的分布
README 将读者导向官方文档站;而在本仓库内,文档源文件位于 docs/,与站点结构一一对应,可作为最权威的版本查阅:
- 框架入口文档:docs/framework/react/quick-start.md、docs/framework/react/overview.md、docs/framework/vue/quick-start.md、docs/framework/svelte/quick-start.md(Solid/Preact/Lit/Angular 同构);
- 核心概念指南:如 docs/framework/react/guides/、docs/framework/vue/guides/,覆盖缓存策略、重取、乐观更新、持久化等主题;
- 框架无关的核心参考:docs/reference/QueryClient.md、docs/reference/QueryCache.md、docs/reference/QueryObserver.md、docs/reference/MutationCache.md;
- ESLint 规则文档:docs/eslint/ 下按规则逐一成篇(如 exhaustive-deps.md、stable-query-client.md);
- 社区资源汇总:docs/community-resources.md。
除文档外,仓库还有两类高价值资源:
examples/:按框架组织的可运行示例(examples/react/、examples/vue/、examples/solid/、examples/svelte/、examples/angular/、examples/lit/、examples/preact/),覆盖basic、pagination、auto-refetching、optimistic-updates、ssr、suspense等场景。例如 examples/angular/auto-refetching/ 演示窗口聚焦自动重取,examples/react/load-more-infinite-scroll/ 演示无限滚动(对应 README 第三行能力)。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(版本由 .nvmrc 与 package.json 中 pnpm@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.ts、retryer.ts、hydration.ts与focusManager/onlineManager中均有可直接核对的实现; - 文档源(
docs/)、可运行示例(examples/)与集成回归工程(integrations/)三者齐备,配合 pnpm + Nx 工作流(pnpm install && pnpm build:all && pnpm run watch),可以在本地完整复现该库的开发与验证链路。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00