用途
该技能面向在 React 19 应用中使用 TanStack Start React Server Components(RSC)的开发场景,用于实现、审查、调试和重构相关代码。当任务提及 @tanstack/react-start/rsc 等内容时适用。
其核心思路是:把 TanStack Start RSC 当作可获取的 React Flight 载荷,而不是框架自有的服务端树。应先从数据归属和缓存归属出发,再选择能满足需求的最小 RSC 原语。
技能激活时的检查项
- 检查 vite.config.* 中的 tanstackStart({ rsc: { enabled: true } })、rsc() 和 viteReact()。
- 检查路由文件中的 loader、loaderDeps、staleTime、ssr 和 errorComponent。
- 检查服务端边界:createServerFn、createServerOnlyFn、.server.*,以及来自 @tanstack/react-start/server 的导入。
- 识别缓存归属:Router loader 缓存、TanStack Query,或 HTTP/服务端缓存。
- 识别刷新路径:router.invalidate()、invalidateQueries、refetchQueries,或 GET 缓存头。
硬性约束
- 路由 loader 是同构的。不要把数据库访问、密钥或仅 Node 可用的 API 直接放进 loader。如果 loader 本身必须使用浏览器 API,将该路由设为 ssr: false。
- renderServerComponent(...) 返回可渲染的 fragment,不支持插槽。
- createCompositeComponent(...) 用于必须接受客户端提供的 children、render props 或组件 props 的服务端渲染 UI。
- 查询缓存的 RSC 值需要 structuralSharing: false。
- 插槽载荷在服务端是不透明的。不要检查、映射或克隆 props.children。
- render-prop 和组件插槽参数必须保持 Flight 可序列化。
- 当前服务端函数校验 API 是 .validator(...)。旧代码片段可能仍显示旧写法,应将其规范化。
- TanStack 自定义序列化目前尚不适用于 RSC 内部。应停留在 Flight 原生支持的值范围内。
需要立即决定的三件事
1)传输/组合原语
- 不需要客户端插槽 -> renderServerComponent
- 客户端交互必须插入服务端渲染的标记内部 -> createCompositeComponent + <CompositeComponent src={...} />
- 需要自定义 Flight 流式传输、API 路由或非标准传输 -> renderToReadableStream、createFromReadableStream、createFromFetch
2)缓存归属
- 以 pathname、params 或 search 为键的路由形态数据 -> Router 缓存
- 独立键空间、后台重新获取或非路由归属 -> TanStack Query
- 服务端或 CDN 上的跨请求复用 -> GET createServerFn + 响应缓存头和/或外部服务端缓存
3)刷新归属
- Router 拥有的 RSC -> router.invalidate()
- Query 拥有的 RSC -> queryClient.invalidateQueries(...) 或 refetchQueries(...)
- Router + Query 混合 -> 有意地同时失效两者;不要假设其中一个会刷新另一个
模式选择
- 路由 loader 中的简单服务端 fragment -> renderServerComponent
- 服务端标记内的交互式插槽 -> createCompositeComponent
- 路由组件需要浏览器 API,但 loader 仍可在服务端预取 -> ssr: 'data-only'
- loader 本身需要浏览器 API -> ssr: false
- 路由缓存键必须包含 search params -> loaderDeps
- Query 管理的 RSC -> useSuspenseQuery + SSR ensureQueryData
- 多个独立 RSC -> 单独的 server functions + Promise.all
- 多个 RSC 共享数据或一起失效 -> 一个 server function 返回多个 renderable 或 source
- 需要隔离的组件失败或错峰显示 -> 从 loader 返回 promise,并在 Suspense 内用 use() 解析
插槽选择
- children:自由组合,无服务端到客户端的数据流
- render props:服务端必须把可序列化数据传入客户端渲染的 UI
- component props:可复用的客户端插槽,具有稳定的类型化 prop 接口
如果准备在服务端使用 Children.map、cloneElement 或检查 children,应停止并改为 render prop。
审查/重构清单
- 所选原语是否是满足需求的最小原语?
- 是 loader 拥有 RSC,还是应由 Query 拥有?
- 路由缓存键是否完整(params + 最小 loaderDeps)?
- 失效是否命中真正的缓存归属?
- 任何 RSC 值的 query options 是否使用 structuralSharing: false?
- 变更是否是显式的 createServerFn({ method: 'POST' }) 调用,而不是隐藏的 server actions?
- 仅服务端的导入是否保留在 server functions 或仅服务端边界内?
- 示例是否使用当前名称(renderServerComponent、.validator),而不是过时名称?
快速调试
- 设置、导出或过时文档不匹配 -> docs/current-api-notes.md
- Composite Component 设计或插槽 bug -> docs/composite-components.md
- 数据过时、重新获取、loader 键、Query 与 Router 归属,或 SSR 模式 -> docs/caching-refresh-ssr.md
- 审查、重构、导入泄漏、错误边界或序列化 bug -> docs/debugging-review.md
- 架构以及 Next/App Router 迁移 -> docs/architecture.md
可复制粘贴的模式
- examples/01-renderable-route-loader.tsx
- examples/02-composite-slots.tsx
- examples/03-query-owned-rsc.tsx
- examples/04-selective-ssr-data-only.tsx
- examples/05-ssr-false-browser-loader.tsx
- examples/06-low-level-flight-api-route.tsx
默认实现顺序
- 将仅服务端的工作保留在 createServerFn 或 createServerOnlyFn 内。
- 从 server function 返回一个 RSC。
- 通过路由 loader 消费它,除非 Query 有明显的归属优势。
- 添加满足新鲜度要求的最小缓存策略。
- 在真正的缓存归属处恰好接入一次失效。
- 仅当客户端必须填充插槽时,才升级到 Composite Components。
- 仅当高层辅助函数无法表达传输时,才升级到低层 Flight API。
适用场景与限制
适用于 React 19 应用中 TanStack Start RSC 的实现、审查、调试与重构,尤其是涉及服务端边界、缓存归属、刷新路径和插槽组合的任务。限制方面:资料未提供该技能的具体安装命令、收费方式、支持平台或效果数据;其约束以资料中列出的硬性不变量为准,不应超出资料范围推断其他功能。