)
TanStack Router 手动安装指南文件路由生成与代码路由配置双模式实战React / Solid【免费下载链接】router A client-first, server-capable, fully type-safe router and full-stack framework for the web (React and more).项目地址: https://gitcode.com/GitHub_Trending/ro/router本文是一份面向 TanStack Router 的完整手动安装Manual Setup实战指南适用于希望在 React 或 Solid 项目中不依赖脚手架、以最小成本接入 TanStack Router 的开发者。读完本文你将掌握两种路由配置模式基于文件系统自动生成路由File-Based Route Generation与纯代码声明路由Code-Based Route Configuration并能理解tanstack/router-plugin在 Vite 中的工作方式、routeTree.gen.ts的生成机制以及类型安全路由注册的原理。准备工作在开始之前你需要一个已经可以正常运行的 React 或 Solid 前端项目例如通过 Vite 创建的项目并确保项目使用 Vite 作为构建工具本指南的插件配置基于 Vite若使用 esbuild、Webpack、Rspack 或纯 CLI 场景可参考仓库中对应的安装文档with-esbuild、with-webpack、with-rspack、with-router-cliindex.html中存在一个根挂载节点div idroot/div项目使用 TypeScript以充分发挥 TanStack Router 的端到端类型安全能力。方式一基于文件的路由生成File-Based Route Generation这是 TanStack Router 推荐的默认用法你在src/routes目录下按约定命名文件插件会在开发与构建时自动把这些文件转换为一棵类型安全的路由树route tree并生成src/routeTree.gen.ts。第 1 步安装依赖核心运行时依赖React 项目tanstack/react-router—— 路由核心库tanstack/react-router-devtools—— 开发期路由调试面板Solid 项目tanstack/solid-routertanstack/solid-router-devtools开发依赖tanstack/router-plugin—— 负责路由树生成、代码分割与 HMR 集成的 Vite/打包器插件以 npm 为例# React npm install tanstack/react-router tanstack/react-router-devtools npm install -D tanstack/router-plugin # Solid npm install tanstack/solid-router tanstack/solid-router-devtools npm install -D tanstack/router-plugin第 2 步配置 Vite 插件在项目根目录的vite.config.ts中加入tanstackRouter插件。注意tanstack/router-plugin必须放在vitejs/plugin-react之前因为路由树生成与转换需要在框架插件处理 JSX 之前完成// vite.config.ts import { defineConfig } from vite import react from vitejs/plugin-react import { tanstackRouter } from tanstack/router-plugin/vite // https://vitejs.dev/config/ export default defineConfig({ plugins: [ // Please make sure that tanstack/router-plugin is passed before vitejs/plugin-react tanstackRouter({ target: react, autoCodeSplitting: true, }), react(), // ..., ], })其中两个常用选项说明如下完整配置项见下文配置项速查target目标框架可选react、solid、vue默认react。Solid 项目请改为target: solidautoCodeSplitting是否开启自动代码分割设为true后插件会把路由的component、errorComponent、notFoundComponent等节点拆分为独立 chunk按需加载。如果你不是使用 Vite 或其它受支持的打包器可以参考 TanStack Router CLI 指南使用tsr watch/tsr generate命令手动生成路由树。第 3 步创建初始文件在项目中创建以下 4 个文件src/routes/__root.tsx注意是两个下划线__前缀表示根布局/路径无关路由src/routes/index.tsxsrc/routes/about.tsxsrc/main.tsxReact 版本import { createRootRoute, Link, Outlet } from tanstack/react-router import { TanStackRouterDevtools } from tanstack/react-router-devtools const RootLayout () ( div classNamep-2 flex gap-2 Link to/ className[.active]:font-bold Home /Link{ } Link to/about className[.active]:font-bold About /Link /div hr / Outlet / TanStackRouterDevtools / / ) export const Route createRootRoute({ component: RootLayout })import { createFileRoute } from tanstack/react-router export const Route createFileRoute(/)({ component: Index, }) function Index() { return ( div classNamep-2 h3Welcome Home!/h3 /div ) }import { createFileRoute } from tanstack/react-router export const Route createFileRoute(/about)({ component: About, }) function About() { return div classNamep-2Hello from About!/div }import { StrictMode } from react import ReactDOM from react-dom/client import { RouterProvider, createRouter } from tanstack/react-router // Import the generated route tree import { routeTree } from ./routeTree.gen // Create a new router instance const router createRouter({ routeTree }) // Register the router instance for type safety declare module tanstack/react-router { interface Register { router: typeof router } } // Render the app const rootElement document.getElementById(root)! if (!rootElement.innerHTML) { const root ReactDOM.createRoot(rootElement) root.render( StrictMode RouterProvider router{router} / /StrictMode, ) }Solid 版本import { createRootRoute, Link, Outlet } from tanstack/solid-router import { TanStackRouterDevtools } from tanstack/solid-router-devtools const RootLayout () ( div classp-2 flex gap-2 Link to/ class[.active]:font-bold Home /Link{ } Link to/about class[.active]:font-bold About /Link /div hr / Outlet / TanStackRouterDevtools / / ) export const Route createRootRoute({ component: RootLayout })import { createFileRoute } from tanstack/solid-router export const Route createFileRoute(/)({ component: Index, }) function Index() { return ( div classp-2 h3Welcome Home!/h3 /div ) }import { createFileRoute } from tanstack/solid-router export const Route createFileRoute(/about)({ component: About, }) function About() { return div classNamep-2Hello from About!/div }/* refresh reload */ import { render } from solid-js/web import { RouterProvider, createRouter } from tanstack/solid-router // Import the generated route tree import { routeTree } from ./routeTree.gen // Create a new router instance const router createRouter({ routeTree }) // Register the router instance for type safety declare module tanstack/solid-router { interface Register { router: typeof router } } // Render the app const rootElement document.getElementById(root)! render(() RouterProvider router{router} /, rootElement)第 4 步理解路由树生成与挂载无论你是通过tanstack/router-plugin在npm run dev/npm run build时自动生成还是在 package scripts 中手动运行tsr watch/tsr generate命令生成的路由树文件都会输出到src/routeTree.gen.ts。你不需要手动编辑该文件main.tsx直接从中导入routeTree并交给createRouter创建路由器实例。如果你采用这种文件路由模式请确认index.html中根div的id为root即div idroot/div与上面main.tsx中getElementById(root)保持一致。从源码看生成器负责将src/routes目录下的文件按照约定转换为路由树配置项routesDirectory默认./src/routes与generatedRouteTree默认./src/routeTree.gen.ts都定义在 packages/router-generator/src/config.ts 的 schema 中而tanstack/router-plugin在 Vite 侧通过tanstackRouter由 packages/router-plugin/src/vite.ts 导出组合了多个底层插件其组成逻辑见 packages/router-plugin/src/core/router-composed-plugin.ts路由生成器generator总是启用当autoCodeSplitting开启时追加代码分割插件开发模式下NODE_ENV ! production且未开启代码分割时追加 HMR 插件同时还会注入内联 CSS 相关默认值。配置项速查以下配置可写在tsr.config.json或直接作为插件 options 传入inline 配置会覆盖文件配置完整 schema 见 packages/router-generator/src/config.ts 与 packages/router-plugin/src/core/config.ts配置项类型/默认值说明targetreact \| solid \| vue默认react生成路由树的目标框架routesDirectory字符串默认./src/routes存放路由文件的目录generatedRouteTree字符串默认./src/routeTree.gen.ts生成的路由树输出路径当disableTypes为true时会自动改为.jsrouteFilePrefix字符串只有匹配该前缀的文件才会被当作路由文件routeFileIgnorePrefix字符串默认-以该前缀开头的文件会被忽略注意不能使用_它是路径无关路由的保留字符源码中有专门校验routeFileIgnorePattern字符串匹配正则的文件被忽略quoteStylesingle \| double默认single生成代码的引号风格semicolons布尔默认false生成代码是否带分号disableLogging布尔默认false关闭生成日志disableTypes布尔默认false关闭生成代码的类型信息输出.jsaddExtensions布尔/字符串默认false为生成的导入添加文件扩展名autoCodeSplitting布尔是否开启路由自动代码分割旧配置experimental.enableCodeSplitting已废弃源码中遇到会直接报错提示迁移codeSplittingOptions对象代码分割的细粒度控制defaultBehavior默认[[component], [errorComponent], [notFoundComponent]]见 packages/router-plugin/src/core/constants.ts、splitBehavior按routeId编程式控制、deleteNodes、addHmrindexToken/routeToken字符串/正则默认index/route文件路由命名中的特殊标记两者不能相同源码中有相等性校验pathParamsAllowedCharacters数组允许出现在路径参数中的额外字符; : $ ,方式二基于代码的路由配置Code-Based Route Configuration如果你更喜欢完全用代码声明路由可以不依赖文件路由生成。下面的示例为了演示简洁将全部代码放在单个文件中官方文档同时提醒虽然代码式配置允许在单文件里声明大量路由甚至 router 实例但随着应用增长仍建议把路由拆分到独立文件以获得更好的组织性与性能。React 版本import { StrictMode } from react import ReactDOM from react-dom/client import { Outlet, RouterProvider, Link, createRouter, createRoute, createRootRoute, } from tanstack/react-router import { TanStackRouterDevtools } from tanstack/react-router-devtools const rootRoute createRootRoute({ component: () ( div classNamep-2 flex gap-2 Link to/ className[.active]:font-bold Home /Link{ } Link to/about className[.active]:font-bold About /Link /div hr / Outlet / TanStackRouterDevtools / / ), }) const indexRoute createRoute({ getParentRoute: () rootRoute, path: /, component: function Index() { return ( div classNamep-2 h3Welcome Home!/h3 /div ) }, }) const aboutRoute createRoute({ getParentRoute: () rootRoute, path: /about, component: function About() { return div classNamep-2Hello from About!/div }, }) const routeTree rootRoute.addChildren([indexRoute, aboutRoute]) const router createRouter({ routeTree }) declare module tanstack/react-router { interface Register { router: typeof router } } const rootElement document.getElementById(app)! if (!rootElement.innerHTML) { const root ReactDOM.createRoot(rootElement) root.render( StrictMode RouterProvider router{router} / /StrictMode, ) }Solid 版本/* refresh reload */ import { render } from solid-js/web import { Outlet, RouterProvider, Link, createRouter, createRoute, createRootRoute, } from tanstack/solid-router import { TanStackRouterDevtools } from tanstack/solid-router-devtools const rootRoute createRootRoute({ component: () ( div classp-2 flex gap-2 Link to/ class[.active]:font-bold Home /Link{ } Link to/about class[.active]:font-bold About /Link /div hr / Outlet / TanStackRouterDevtools / / ), }) const indexRoute createRoute({ getParentRoute: () rootRoute, path: /, component: function Index() { return ( div classp-2 h3Welcome Home!/h3 /div ) }, }) const aboutRoute createRoute({ getParentRoute: () rootRoute, path: /about, component: function About() { return div classp-2Hello from About!/div }, }) const routeTree rootRoute.addChildren([indexRoute, aboutRoute]) const router createRouter({ routeTree }) declare module tanstack/solid-router { interface Register { router: typeof router } } const rootElement document.getElementById(app)! render(() RouterProvider router{router} /, rootElement)两种模式的差异与选择文件路由File-Based路由即文件目录结构即路由层级适合路由数量多、需要代码分割与按需加载的中大型应用。路由树由插件自动生成新增页面只需新建文件。代码路由Code-Based所有路由通过createRootRoute/createRoute声明并通过rootRoute.addChildren([...])手动组装层级适合路由规模小、或希望完全掌控路由声明的场景。两种模式在运行时是等价的最终都会得到一个routeTree与createRouter({ routeTree })创建的路由器实例并且都需要通过declare module的Register接口完成类型注册从而让Link、useNavigate、useSearch等 API 获得端到端的类型推导。运行与验证完成上述任一方式的配置后npm run dev启动开发服务器你会看到访问/显示 Welcome Home!访问/about显示 Hello from About!顶部导航栏的当前页链接会因[.active]:font-bold而加粗开发模式右下角出现 TanStack Router Devtools 面板React/Solid 各自对应的 devtools 包可用于查看路由树、导航历史与匹配状态。若要继续深入学习可以从文件命名约定、路径参数与搜索参数开始相关 API 参考见 docs/router/api路由概念见 docs/router/routing。仓库中还有大量可直接对照的端到端示例例如 e2e/react-router/basic-file-based 与 e2e/solid-router/basic-file-based它们展示了文件路由模式在完整应用中的落地形态。【免费下载链接】router A client-first, server-capable, fully type-safe router and full-stack framework for the web (React and more).项目地址: https://gitcode.com/GitHub_Trending/ro/router创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考