Epic Stack 路由系统演进:从 remix-flat-routes 迁移到 react-router-auto-routes

Epic Stack 路由系统演进:从 remix-flat-routes 迁移到 react-router-auto-routes Epic Stack 路由系统演进从 remix-flat-routes 迁移到 react-router-auto-routes【免费下载链接】epic-stackThis is a Full Stack app starter with the foundational things setup and configured for you to hit the ground running on your next EPIC idea.项目地址: https://gitcode.com/GitHub_Trending/ep/epic-stack本篇文章以 Epic Stack 仓库中的架构决策记录 docs/decisions/045-rr-auto-routes.md 为核心系统讲解该项目如何将路由清单生成从remix-flat-routes迁移至react-router-auto-routes包括迁移动机、实际配置方式、文件系统路由约定路由组、动态参数、嵌套布局、资源路由、共置模块以及调试与验证手段。读完本文你将掌握 Epic Stack 当前基于react-router-auto-routes的路由组织规范能够正确新增页面、嵌套布局与资源路由并理解这一架构决策对后续升级 React Router 的意义。背景为什么放弃 remix-flat-routesEpic Stack 早期依赖remix-flat-routes将app/routes目录转换为 React Router 在构建期消费的路由清单route manifest。该库帮助项目引入了可预测的约定式文件路由但在长期使用中暴露了一个结构性痛点它以后缀的混合约定将共置colocation作为默认模式随着应用规模增长路由目录结构容易变得不够清晰、难以组织。与此同时社区出现了与 React Router 原生约定和 API 对齐的react-router-auto-routes仓库当前锁定版本为^0.8.4见 package.json 的 devDependencies。迁移到它的收益包括贴近上游约定自动路由生成遵循 React Router 官方约定降低未来升级 React Router 时的破坏风险减少自研工具面需要维护的自定义工具链更少迁移路径更清晰随着 React Router 自身演进项目可以更平滑地跟进。决策内容替换路由清单生成器根据 docs/decisions/045-rr-auto-routes.md 的 Decision 一节项目正式决定用react-router-auto-routes替换remix-flat-routes来生成应用路由清单新工具纳入构建与开发流水线react-router build、react-router dev原remix-flat-routes的配置按新约定迁移。该决策记录的 Status 为accepted2025-10-15意味着这是当前生效的既定方向而非未定草案。落地配置app/routes.ts 与 react-router.config.ts路由清单入口app/routes.ts迁移后的实际配置位于仓库根目录的 app/routes.ts全文如下import { type RouteConfig } from react-router/dev/routes import { autoRoutes } from react-router-auto-routes export default autoRoutes({ ignoredRouteFiles: [ .*, **/*.css, **/*.test.{js,jsx,ts,tsx}, **/__*.*, // 这是为了让服务端工具函数与路由共置在同一目录下 // 而无需额外创建子目录。如果确实需要包含 server 或 // client 字样的路由文件名请使用转义括号写法例如 // my-route.[server].tsx **/*.server.*, **/*.client.*, ], }) satisfies RouteConfig这段配置值得逐项拆解配置项作用ignoredRouteFiles声明哪些文件不参与路由生成是 glob 模式数组.*忽略以点开头的隐藏文件如.DS_Store**/*.css忽略样式文件防止.css被误当作路由**/*.test.{js,jsx,ts,tsx}忽略单元测试文件例如仓库中的 app/routes/_auth/auth.$provider/callback.test.ts**/__*.*忽略以双下划线开头的私有模块目录**/*.server.*忽略服务端共置工具如 app/routes/_auth/login.server.ts**/*.client.*忽略客户端共置工具satisfies RouteConfig让 TypeScript 校验配置符合react-router/dev/routes的类型约束其中**/*.server.*/**/*.client.*的注释给出了一个重要约定服务端或客户端专属工具可以与路由文件同目录共置但要避免在文件名中使用server/client字样万一路由本身确实需要这些关键词用方括号转义即可如my-route.[server].tsx。构建期配置react-router.config.ts路由发现行为在 react-router.config.ts 中通过routeDiscovery: { mode: initial }声明默认开启 SSRssr: true。autoRoutes生成的路由清单正是在此构建配置之下被消费的两个文件配合共同决定了最终的 URL 结构。文件系统路由约定react-router-auto-routes 的命名规则react-router-auto-routes是对 React Router 原生文件路由约定的增强实现。正如 docs/routing.md 所述它的核心理念是鱼与熊掌兼得路由与所使用代码共置前缀的共置模块保持有组织的目录结构让相关路由按需聚合。以下约定均有仓库真实文件佐证。路由组Route Groups_前缀目录以_开头的目录只用于组织代码不影响 URL。典型例子_auth/认证相关路由登录、注册、找回密码等见 app/routes/_auth_marketing/营销页面首页、关于、隐私政策等见 app/routes/_marketing_seo/SEO 路由sitemap、robots.txt见 app/routes/_seo。例如app/routes/_auth/login.tsx对应 URL/login_marketing/about.tsx对应/about。动态参数$前缀文件与目录用$表示 URL 参数编译期自动映射为 React Router 的:param$username.tsx→/users/:username目录级参数app/routes/users/$username/notes/$noteId.tsx对应/users/:username/notes/:noteId仓库中 app/routes/users/$username 即是真实示例。参数可以通过 loader 的params读取类型安全例如 docs/skills/epic-routing/SKILL.md 中展示的// app/routes/users/$username/index.tsx export async function loader({ params }: Route.LoaderArgs) { const username params.username const user await prisma.user.findUnique({ where: { username } }) return { user } }嵌套布局_layout.tsx_layout.tsx为子路由提供共享布局子路由渲染在Outlet /位置。仓库中的嵌套布局示例app/routes/settings/profile/_layout.tsx管理个人设置下的所有子页change-email、connections、passkeys、password、photo、two-factor 等app/routes/users/$username/notes/_layout.tsx则是笔记模块的二级布局。当同一段路径既需要父级 UI 又需要索引页时就形成布局 index的标准组合。资源路由无 UI 的路由只导出loader或action或两者、不导出默认组件的文件称为资源路由用于 API、下载、Webhook 等场景。仓库实例app/routes/_seo/robots[.]txt.ts 与 app/routes/_seo/sitemap[.]xml.ts 用方括号转义点号使 URL 中能保留字面量.。共置模块前缀前缀表示与路由共置、但不是路由本身的模块。仓库典型示例是app/routes/users/$username/notes/shared/目录其中的 note-editor.tsx 是被新建与编辑笔记两条路由共用的编辑器组件含表单校验 Schema 与MAX_UPLOAD_SIZE等逻辑。_marketing/logos/中的 SVG Logo 资源同理——它们放在路由目录旁却不产生任何 URL。这与remix-flat-routes时代后缀的默认共置模式恰好相反新约定下共置是有意为之的特例普通路由默认是层级化目录结构更清晰。查看生成的路由npx react-router routes在应用根目录运行以下命令即可查看基于当前文件结构生成的全部路由JSX 风格输出这是熟悉该约定最实用的调试手段npx react-router routesapp/routes 的完整目录树72 个文件、17 个目录会生成一份对应的Routes树节选关键片段Routes Route fileroot.tsx Route path* fileroutes/$.tsx / Route pathauth/:provider/callback fileroutes/_auth/auth.$provider/callback.ts / Route pathauth/:provider index fileroutes/_auth/auth.$provider/index.ts / Route pathlogin fileroutes/_auth/login.tsx / Route pathonboarding index fileroutes/_auth/onboarding/index.tsx / Route pathrobots.txt fileroutes/_seo/robots[.]txt.ts / Route pathsitemap.xml fileroutes/_seo/sitemap[.]xml.ts / Route pathsettings/profile fileroutes/settings/profile/_layout.tsx Route pathchange-email fileroutes/settings/profile/change-email.tsx / Route index fileroutes/settings/profile/index.tsx / Route pathtwo-factor fileroutes/settings/profile/two-factor/_layout.tsx Route index fileroutes/settings/profile/two-factor/index.tsx / Route pathverify fileroutes/settings/profile/two-factor/verify.tsx / /Route /Route Route pathusers/:username index fileroutes/users/$username/index.tsx / Route pathusers/:username/notes fileroutes/users/$username/notes/_layout.tsx Route path:noteId fileroutes/users/$username/notes/$noteId.tsx / Route path:noteId/edit fileroutes/users/$username/notes/$noteId_.edit.tsx / Route index fileroutes/users/$username/notes/index.tsx / Route pathnew fileroutes/users/$username/notes/new.tsx / /Route Route pathusers index fileroutes/users/index.tsx / /Route /Routes从这段输出可以印证多个约定细节_auth、_marketing、_seo路由组不出现在路径中auth.$provider/callback.ts中的$provider被编译为:providerrobots[.]txt.ts的转义点号保真为robots.txt$noteId_.edit.tsx通过$noteId_语法表示参数段后紧跟静态段edit_layout.tsx生成嵌套Route子路由挂在其下资源路由robots、sitemap 等与普通路由在清单中无本质区别仅文件内容不导出组件。编写约定速查结合 docs/skills/epic-routing/SKILL.md 与仓库实际结构新增路由时应遵循需求文件名 / 目录示例普通页面about.tsxapp/routes/_marketing/about.tsx段索引页index.tsxapp/routes/users/index.tsx动态参数$param.tsxapp/routes/users/$username/index.tsx嵌套布局_layout.tsxapp/routes/settings/profile/_layout.tsx参数后接静态段$param_.action.tsxapp/routes/users/$username/notes/$noteId_.edit.tsx带点号的资源路由name[.]ext.tsapp/routes/_seo/robots[.]txt.ts共置工具模块shared/、*.server.*app/routes/users/$username/notes/shared/note-editor.tsx同时需要注意布局组件必须渲染Outlet /否则子路由不会显示资源路由不要导出默认组件参数使用$param写法而非:param或[param]路由组_目录不会出现在 URL 中遵循尽量简单原则不要在真正需要之前就堆砌嵌套结构。迁移的后果与验证决策记录列出了三项核心后果升级兼容性提升自动路由生成遵循 React Router 约定未来升级 React Router 时破坏风险降低文档与示例同步更新贡献者需要遵循react-router-auto-routes的命名与组织规则仓库因此更新了 docs/routing.md 与 docs/skills/epic-routing/SKILL.md 以反映新的目录语义全量验证通过所有既有功能经npm run validate验证在新路由系统下工作正常。npm run validate定义于 package.json实际串联了test --run、lint、typecheck与test:e2e:run四条流水线其中typecheck会先执行react-router typegen生成类型再运行tsc——这保证了路由清单的类型信息与源码始终一致。而 tests/e2e 下的 Playwright 用例如 notes.test.ts、onboarding.test.ts则从端到端层面覆盖了这些路由的真实可访问性。总结从remix-flat-routes到react-router-auto-routesEpic Stack 完成了一次向 React Router 原生约定靠拢的架构收敛_前缀组织路由组、$声明动态参数、_layout.tsx构建嵌套布局、前缀支持共置模块配合app/routes.ts中细粒度的ignoredRouteFiles白名单与npx react-router routes的可视化输出路由系统的可维护性与可迁移性都得到了实质提升。对使用该模板启动新项目的开发者而言掌握这套约定就等于掌握了整个应用页面与接口的地图。【免费下载链接】epic-stackThis is a Full Stack app starter with the foundational things setup and configured for you to hit the ground running on your next EPIC idea.项目地址: https://gitcode.com/GitHub_Trending/ep/epic-stack创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考