@tanstack/query-core 5.102 版本解读:query/infiniteQuery 新命令式 API、hydration 性能优化与内存释放

@tanstack/query-core 5.102 版本解读:query/infiniteQuery 新命令式 API、hydration 性能优化与内存释放 tanstack/query-core 5.102 版本解读query/infiniteQuery 新命令式 API、hydration 性能优化与内存释放【免费下载链接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/querytanstack/query-core是 TanStack Query 框架无关的核心层react-query、vue-query、solid-query、svelte-query 等框架适配包均建立在它之上。本文以 packages/query-core/CHANGELOG.md 为主线逐条解读 5.90 至 5.102.8 版本的关键变更并结合 queryClient.ts、hydration.ts、environmentManager.ts 等源码说明这些变更对实际开发SSR 水合、Suspense、无限查询、内存占用、类型推断的影响帮助你在升级时准确评估风险与收益。一、版本概览与当前状态根据 package.json当前仓库中tanstack/query-core的版本为5.102.8包描述为 The framework agnostic core that powers TanStack Query采用type: module同时提供import/require双通道产物与 modern/legacy 两套类型声明。CHANGELOG 覆盖的版本区间与核心主题如下版本区间主题关键词5.102.x新命令式 APIquery/infiniteQuery、hydration 性能、内存释放、类型改进5.100.x – 5.101.x泛型推断修复NoInfer、retryOnMount回调、SSR 水合行为5.90.x – 5.99.xenvironmentManager、streamedQuery、timeoutManager、observer 调度修复其中5.102.0是信息量最大的一个 Minor 版本值得单独展开。二、5.102.0新的命令式 APIquery与infiniteQuery5.102.0 引入了一组新的命令式方法并弃用了旧的fetchQuery、prefetchQuery、fetchInfiniteQuery、prefetchInfiniteQuery、ensureQueryData等 API。2.1 新增方法与用法// 主动拉取并返回 Promise等价于旧的 fetchQuery await queryClient.query({ queryKey: [posts], queryFn: fetchPosts, }) // 无限查询版本内部自动带上 _type: infinite await queryClient.infiniteQuery({ queryKey: [posts, infinite], queryFn: fetchPage, initialPageParam: 0, }) // 设置 staleTime 为 static等价于旧的 ensureQueryData 语义 await queryClient.query({ queryKey: [posts], queryFn: fetchPosts, staleTime: static })从 queryClient.ts 源码 可以看到infiniteQuery的实现非常简洁——它先把options._type infinite写入选项再委托给query()infiniteQuery(options) { options._type infinite return this.query(options as any) }_type字段正是 hydration.ts 中DehydratedQuery.queryType值可为infinite的来源也是query()在底层构建InfiniteQueryObserver行为的类型标记。2.2 旧方法上的弃用标记源码中对旧方法全部添加了deprecatedJSDoc 标记例如/** deprecated Use queryClient.query(options) instead. This method will be removed in the next major version. */ fetchQuery(...) /** deprecated Use queryClient.infiniteQuery({ ...options, staleTime: static }) instead. ... */ ensureQueryData(...)完整列表见 queryClient.ts。这意味着升级到 5.102 后使用旧方法的代码会收到类型层面的弃用警告下个大版本将直接移除建议在升级本版本时同步迁移。2.3 相关类型改进同一版本中还修复了两个与类型相关的问题queryOptions/infiniteQueryOptions返回类型修复导出类型在声明文件中泄露内部 data tag 符号的问题PR #11224使推断出的 options 可以安全地发布到.d.ts中mutation variables 可选性当undefined extends TVariables时mutation 的variables参数变为可选PR #8737避免了对可能为undefined的变量强行必填。三、hydration 相关变更性能、导出与行为修复3.1 导出dehydrateQuery5.102.05.102.0 将dehydrateQuery从内部函数提升为公开导出index.ts 与 hydration.ts 中均有对应实现。它的签名如下export function dehydrateQuery( query: Query, serializeData?: TransformerFn, shouldRedactErrors?: (error: unknown) boolean, ): DehydratedQuery它返回包含dehydratedAt、state可被serializeData序列化、queryKey、queryHash的对象当查询状态为pending时还会附带一个promise字段由dehydratePromise生成见 hydration.ts。在非生产环境下若被水合的 pending promise 最终 reject会打印包含queryHash的红色错误日志生产环境则统一替换为redacted错误避免泄漏服务端错误细节。3.2 hydration 性能优化5.102.0跳过无操作的数据变换与默认错误脱敏回调PR #11253在dehydrate过程中若未配置serializeData或shouldRedactErrors则不再调用默认的 no-op 变换函数减少不必要的函数调用开销pending 查询的 de/rehydration 不再产生未处理的 Promise 拒绝5.90.3PR #9752dehydratePromise内部对返回的 promise 追加.catch(noop)见 hydration.ts既保证查询缓存能拿到正确结果又避免在预取环境产生 unhandled rejection 警告。3.3 水合行为修复5.100.1修复已解析的 promise 被水合时查询短暂显示 pending/fetching的问题PR #10444。这正是 hydrate 实现 中tryResolveSync(promise)的作用——同步解析成功的数据直接进入 state不再走 retryer 路径从而避免闪烁5.102.1hydrate的入参类型从DehydratedState放宽为PartialDehydratedStatePR #11260允许省略 mutation 或 query 集合例如只有 queries 的 payloadhydrate 签名 已同步更新且内部用?.forEach做可选遍历。3.4 无限查询在 SSR 水合中的行为保持5.100.25.100.2 修复了无限查询在 SSR 水合期间的行为PR #10074dehydrateQuery中queryType字段infinite被保留hydrate时通过_type: queryType传递见 hydration.ts确保水合后的无限查询仍以正确的 infinite 语义运行。四、内存与资源释放retryer 与订阅生命周期5.102.0 集中修复了一批长生命周期对象持有短生命周期引用导致的内存滞留问题这是本次版本最值得关注的一类修复查询 retryer 释放PR #11163fetch 结束settle后立即释放查询的 retryer已 settled 的 promise 不再持有 fetch 原始结果与结构共享的state.data并存的内存占用被消除查询被 reset 或 remove 后同样生效mutation retryer 释放PR #11218mutation 执行结束后释放其 retryermutation 的 result、variables 与 context 不再因 mutation cache 的保留而长期驻留内存observer 列表原地移除PR #11214unsubscribe时不再复制 observer 列表改为原地删除降低每次退订的 churn 开销定时器泄漏修复5.95.1 / 5.95.2PR #10323 / #10325确保 Node.js 的Timeout不会泄漏——注意 timeoutManager.ts 是专门管理超时调度的模块timer ID 边界情况5.97.0PR #10401改用显式undefined判断 timer ID使自定义TimeoutProvider返回0作为合法 timer ID 时也能被正确清除。五、Suspense 与 observer 通知行为程序化数据更新也能解除 SuspensePR #11036此前fetchOptimistic只返回 fetch promise即使缓存中已有setQueryData或streamedQuery写入的数据Suspense 边界也要等queryFn完成才能解除。修复后通过Promise.race配合 cache 订阅一旦数据可用立即解除 SuspensependingThenable 的滞后回调不再覆盖状态PR #11128持有resolve/reject引用并在 settled 之后调用曾导致 thenable 的status/reason与实际 promise 不一致现已被忽略suspense 模式下跳过 combine5.100.3PR #10576查询即将挂起时不调用combine避免无谓计算useSuspenseQueries重复 queryKey 防死循环5.90.11PR #9886重复 key 不再引发无限渲染循环同步退订通知PR #11234同一查询更新期间若有 observer 同步退订仍会通知到其余所有 observerresetQueries保留匹配集PR #11211修复query.reset()改变状态前已匹配的查询集合被丢失的问题isPlaceholderData与 select 错误清理PR #11161、PR #11011切换到无数据的查询时清除过期的select错误select在 placeholder 数据上抛错时重置isPlaceholderData避免上一个查询的错误泄漏到新结果。useQueries 性能专项5.102.0无 combine 时跳过结果跟踪PR #11225通知useQueries监听器时若未提供combine函数跳过不必要的 result tracking避免重复同步同一 tracked 属性PR #11215不再对所有 observer 反复同步同一属性falsy combine 结果记忆化PR #11065当combine函数与查询结果均未变化时记忆化 falsy 结果如null避免引用不稳定引发重渲染动态变化时更新 stable combine 引用5.90.19PR #9954查询动态变化时稳定的combine引用也能正确更新查询数量变化的竞态5.90.16PR #9973修复useQueries在查询长度变化时的竞态条件。六、类型系统改进5.100.x 系列弃用自定义NoInfer改用 TS 内置5.100.13PR #10593要求TypeScript ≥ 5.4。这是为了修复NoInferX[K]在泛型上下文中不满足X[K]可赋值性的问题issue #9937。注意这是升级时的一个硬性前提条件请先确认项目 TS 版本persister 泛型推断调整5.100.2 / 5.100.10PR #10510 / #10601允许persister参与TQueryFnData推断修复声明了参数类型的queryFn与 typed persister 的虚假重载不匹配issue #7842同时保留persister槽位上的NoInferTQueryKey防止TQueryKey被拓宽到增强后的约束避免DataTag品牌化返回值在逆变位置不可赋值QueryFilters 联合类型5.90.10 / 5.90.9 / 5.90.8允许不同长度的QueryFilters联合、支持部分 query key 匹配、不丢失 readonly 修饰MutationKey 类型去重5.90.4PR #9754移除MutationKey中重复的Array条件分支。七、核心配置导出与新管理器7.1 导出QueryCacheConfig与MutationCacheConfig5.102.2这两个配置类型此前仅存在于 queryCache.ts 与 mutationCache.ts 中5.102.2 起通过 index.ts 对外导出允许自定义缓存时获得完整类型提示。两者均接受onError、onSuccess、onSettled等回调见对应测试 queryCache.test.tsx 与 mutationCache.test.tsx。7.2environmentManager5.91.0PR #10199新增环境检测管理器源码见 environmentManager.tsexport const environmentManager { isServer, // () boolean setIsServer(isServerValue: IsServerValue), // 全局覆盖服务端检测 }它允许在测试或特殊运行时如边缘函数中覆写isServer的判断结果。相关行为由 environmentManager.test.tsx 覆盖并在 focusManager.ts、onlineManager.ts 等模块中配合使用。八、streamedQuery 与 AbortSignal 相关修复错误状态下 reset refetch 保持错误5.91.2PR #10287定义了initialData时reset refetch 不再丢失 error 状态reducer 只调用一次5.90.14PR #9970修复streamedQueryreducer 被重复调用的问题signal 感知5.90.13PR #9963context.signal对streamedQuery生效空流不返回 undefined5.90.10PR #9876流没有产出值时不再返回undefineddataUpdatedAt缺失5.101.1PR #10610修复在水合前已 resolve 的流式查询缺少dataUpdatedAt的问题无限查询的 AbortSignal reason 传播5.100.7abort 时自定义的reason能正确传递给无限查询。九、其余值得关注的 Patch 修复disabled 查询 observer 不再调度 stale timeout5.102.4PR #11293避免为已禁用的 observer 安排无意义的重取定时器MutationObserver重新附加PR #11172React 在 mutation 中途 tear down 并重建订阅时observer 会重新挂到当前 mutation 上useMutation结果不再卡在pendingonMutate同步执行5.90.20PR #10066未配置mutationCache.config.onMutate时onMutate回调改为同步运行减少竞态窗口错误状态下现有数据视为过期5.90.15PR #9927查询进入错误状态时已有数据一律视为 stale促使尽快重取replaceEqualDeep最大深度5.90.17PR #10032修复深度过大时的递归问题partialMatchKey性能5.101.3PR #11084优化部分 key 匹配的底层实现包体精简5.102.5PR #11302移除未使用的 symbol description、简化内部辅助函数降低 query-core 的 bundle 体积isFetchedAfterMount修正5.90.6PR #9743应用initialData的场景下该标记行为更准确水合时的.then/.catch挂载时机5.90.7PR #9847只有 promise 确实被 dehydrate 时才附加.then/.catch最后 observer 退订时取消暂停的初始 fetch5.91.1PR #10291避免无人消费的请求继续占用资源移除实验性 render-time prefetchingPR #11221删除experimental_prefetchInRender相关能力与查询结果上的promise属性属于破坏性清理若你的代码依赖实验 API 需注意5.90.18 曾对齐其 rejection 行为5.102.0 正式移除。十、升级建议与验证方式TypeScript 版本5.100.13 起依赖 TS ≥ 5.4 的内置NoInfer升级前先确认API 迁移将fetchQuery/prefetchQuery/fetchInfiniteQuery/prefetchInfiniteQuery/ensureQueryData迁移到queryClient.query/queryClient.infiniteQueryensureQueryData语义对应staleTime: static留意实验性 prefetch API 已被移除水合 payloadhydrate已接受 partial state若你手写水合数据可省略空集合dehydrateQuery现已公开导出可直接复用内存敏感场景长驻 cache 的查询/突变不再持有 settled retryer可关注监控内存下降自定义TimeoutProvider若返回0作为 timer ID升级后可被正确清除验证仓库提供多版本 TS 类型测试见 package.json 中test:types:*覆盖 TS 5.6 至 7.0核心逻辑测试可运行pnpm --filter tanstack/query-core test:libvitest。示例用法可参考 react 示例 与 vue 示例 中各项目的queryClient配置。结语5.90 至 5.102.8 的tanstack/query-core演进主线非常清晰统一并现代化命令式 API、系统性消除内存滞留、为 SSR/Suspense 场景打磨水合行为、并在不牺牲类型安全的前提下提升运行时性能。升级时优先处理 API 迁移与 TS 版本两个前置条件即可平滑享受这些底层改进带来的收益。【免费下载链接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/query创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考