整合Query与Router:设计一套完整的Feature架构

路由段与 Feature 模块对齐 — 每个业务域一棵小树

你要产出的,是「以业务域为中心」的一整套 Feature 模块,而不是「以技术细节」碎片堆叠。第一步,就是让路由结构和 Feature 结构对齐:一个业务域 = 一棵小路由树 + 一整个 Feature 目录

1. 拆出一个业务域 Feature 目录

posts 为例,在 src/features/posts 下建出一个最小结构:

bashsrc/ features/ posts/ routes/ postsRoute.tsx postDetailRoute.tsx api/ postsApi.ts queries/ postsKeys.ts usePostsQuery.ts usePostQuery.ts components/ PostsList.tsx PostDetail.tsx ui/ PostsFallback.tsx README.md

含义:

  • routes/:只关心 URL 结构、路由树、入口组件
  • api/:只关心 和服务端打交道的函数(server functions / HTTP 封装)
  • queries/:只关心 React Query/TanStack Query 的 key 和 hooks
  • components/:和该业务域强绑定的 UI 组件
  • ui/:错误、加载、空状态等跨页面可共享 UI
  • README.md:简单写清这棵树怎么长、约定是啥

2. 让路由树长在 Feature 里面

在 TanStack Start(或 TanStack Router)里,你通常会有一个「路由注册点」,比如 src/routes/__root.tsx
我们希望:posts 的子路由由 features/posts/routes 负责声明,而不是在 root 里手写一堆 /posts/*

features/posts/routes/postsRoute.tsx 示例(伪代码,按你项目的实际 API 调整):

ts// src/features/posts/routes/postsRoute.tsx import { createFileRoute } from "@tanstack/react-router" import { PostsList } from "../components/PostsList" import { PostsFallback } from "../ui/PostsFallback" export const postsRoute = createFileRoute("/posts")({ component: PostsList, pendingComponent: () => <PostsFallback variant="loading" />, errorComponent: () => <PostsFallback variant="error" />, })

postDetailRoute

ts// src/features/posts/routes/postDetailRoute.tsx import { createFileRoute } from "@tanstack/react-router" import { PostDetail } from "../components/PostDetail" import { PostsFallback } from "../ui/PostsFallback" export const postDetailRoute = createFileRoute("/posts/$postId")({ component: PostDetail, pendingComponent: () => <PostsFallback variant="loading" />, errorComponent: () => <PostsFallback variant="error" />, })

然后在集中注册的地方(例如 src/routes/index.ts 或 root route 配置),只做「拼树」:

tsimport { postsRoute } from "../features/posts/routes/postsRoute" import { postDetailRoute } from "../features/posts/routes/postDetailRoute" export const routeTree = rootRoute.addChildren([ postsRoute, postDetailRoute, ])

关键点:

  • 路由的「分叉设计」发生在 Feature 内部
  • 根部只做「挂树」,不关心业务细节
  • 以后加 posts 下面的任何新路由,只动 features/posts/routes/*

3. 用一张小图看「每个业务域一棵小树」

Rendering diagram…
  • postsuserssettings 每一个都对齐到 src/features/{domain}
  • 你只要看到 URL 前缀 /posts,就知道「去 features/posts 找」

想象你的路由是森林,每个业务域是一棵树;路由文件、API、Query hooks 都长在同一棵树上,找问题和扩展功能都会更快。

1 / 4