十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

TanStack Router 插件实战指南:文件路由生成与自动代码分割(@tanstack/router-plugin)

TanStack Router 插件实战指南:文件路由生成与自动代码分割(@tanstack/router-plugin) TanStack Router 插件实战指南文件路由生成与自动代码分割tanstack/router-plugin【免费下载链接】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-pluginv1.168.37为核心系统讲解 TanStack Router 官方打包器插件的安装接入、全部配置项、自动代码分割原理、路由重构工作流与高频踩坑点。读完本文你将能够在 Vite、Webpack、Rspack、esbuild 四种构建体系中正确接入该插件理解routeTree.gen.ts的生成机制与三个子插件的协作关系并掌握autoCodeSplitting下按路由精细控制分割粒度的实战能力。一、插件定位与核心职责tanstack/router-plugin是 TanStack Router 的打包器插件通过 unplugin 统一封装为 Vite、Webpack、Rspack、esbuild 提供两种核心能力文件路由生成Route Generation监听routesDirectory下的路由文件自动生成类型安全的routeTree.gen.ts自动代码分割Automatic Code Splitting在构建期把路由文件按可配置的分组拆成懒加载 chunk无需手写createLazyRoute。从仓库的 package.json 可以看到插件通过./vite、./webpack、./rspack、./esbuild、./context等多个子路径导出入口依赖tanstack/router-generator路由树生成器、tanstack/router-core类型与路由核心、chokidar文件监听与zod配置校验并可选 peer 依赖各框架插件tanstack/react-router、vite-plugin-solid等。CRITICAL在 Vite 配置中router 插件必须位于框架插件React、Solid、Vue之前。顺序错误会导致路由生成与代码分割静默失败——这一点在后文「工作原理」与「常见错误」中会给出源码级验证。二、安装在项目根目录安装为开发依赖npm install -D tanstack/router-plugin本仓库使用 pnpm workspace包名版本为1.168.37见 packages/router-plugin/package.json要求 Node20.19支持 Vite5.0.0含 6/7/8与 Webpack5.92.0。三、四种构建体系的接入配置3.1 Vite最常见// vite.config.ts import { defineConfig } from vite import react from vitejs/plugin-react import { tanstackRouter } from tanstack/router-plugin/vite export default defineConfig({ plugins: [ // MUST come before react() tanstackRouter({ target: react, autoCodeSplitting: true, }), react(), ], })仓库中的真实 e2e 工程也遵循这一顺序例如 e2e/react-router/basic-file-based/vite.config.jsplugins: [ tailwindcss(), tanstackRouter({ target: react }), react(), ],3.2 Webpack// webpack.config.js const { tanstackRouter } require(tanstack/router-plugin/webpack) module.exports { plugins: [ tanstackRouter({ target: react, autoCodeSplitting: true, }), ], }3.3 Rspack// rspack.config.js const { tanstackRouter } require(tanstack/router-plugin/rspack) module.exports { plugins: [ tanstackRouter({ target: react, autoCodeSplitting: true, }), ], }3.4 esbuildimport { tanstackRouter } from tanstack/router-plugin/esbuild import esbuild from esbuild esbuild.build({ plugins: [ tanstackRouter({ target: react, autoCodeSplitting: true, }), ], })说明各入口都是同一份 unplugin 工厂函数的打包器适配导出路径与 package.json 的exports字段一一对应。四、配置项全解插件的配置由 core/config.ts 中的 zod schema 统一校验分为核心、文件约定、代码分割、输出四组。4.1 核心选项Core OptionsOptionTypeDefaultDescriptiontargetreact \| solid \| vuereact目标框架routesDirectorystring./src/routes路由文件所在目录generatedRouteTreestring./src/routeTree.gen.ts生成的路由树文件路径autoCodeSplittingbooleanundefined是否启用自动代码分割enableRouteGenerationbooleantrue设为false可关闭路由生成其中target会直接决定插件编译时使用哪个框架的标识符与产物。源码 code-splitter/framework-options.ts 中维护了三套映射React 对应tanstack/react-router、Solid 对应tanstack/solid-router、Vue 对应tanstack/vue-router标识符均为createFileRoute、lazyFn、lazyRouteComponent传入不支持的框架会直接抛出Unsupported framework错误。routesDirectory支持绝对路径相对路径会以构建根目录process.cwd()或 Vite 的config.root为基准拼接见 router-generator-plugin.ts。4.2 文件约定选项File Convention OptionsOptionTypeDefaultDescriptionrouteFilePrefixstringundefined路由文件前缀过滤routeFileIgnorePrefixstring-以该前缀开头的文件被排除出路由routeFileIgnorePatternstringundefined按正则模式排除文件indexTokenstring \| RegExp \| { regex: string; flags?: string }index标识 index 路由的 tokenrouteTokenstring \| RegExp \| { regex: string; flags?: string }route标识路由配置文件的 tokenrouteFileIgnorePrefix默认值为-即形如-component.tsx这类以连字符开头的文件不会被当作路由indexToken/routeToken支持字符串、正则或{ regex, flags }对象三种形态用于自定义index路由与.route.tsx配置文件的识别规则。4.3 输出选项Output OptionsOptionTypeDefaultDescriptionquoteStylesingle \| doublesingle生成代码的引号风格semicolonsbooleanfalse生成代码是否使用分号disableTypesbooleanfalse关闭生成的 TypeScript 类型disableLoggingbooleanfalse关闭插件日志addExtensionsboolean \| stringfalse为 import 添加文件扩展名enableRouteTreeFormattingbooleantrue是否格式化生成的路由树quoteStyle、semicolons等选项直接控制routeTree.gen.ts的生成风格便于与团队 lint/prettier 规则对齐disableTypes适用于纯 JS 工程仓库js-only-file-based类 e2e 场景即属此类。五、自动代码分割codeSplittingOptions开启autoCodeSplitting: true后可用codeSplittingOptions精细控制分割策略tanstackRouter({ target: react, autoCodeSplitting: true, codeSplittingOptions: { // 所有路由的默认分组 defaultBehavior: [[component], [errorComponent], [notFoundComponent]], // 按路由定制分割 splitBehavior: ({ routeId }) { if (routeId /dashboard) { // 对 dashboard 路由把 loader 和 component 放在同一个 chunk return [[loader, component], [errorComponent]] } // 返回 undefined 则回退到 defaultBehavior }, }, })5.1 分组Groupings的合法取值源码 config.ts 中的splitGroupingsSchema约束了分组必须是「数组的数组」内部元素只能取自五个路由节点loadercomponentpendingComponenterrorComponentnotFoundComponent且元素在整个分组中不得重复例如[[component], [component, loader]]会直接校验失败并给出错误信息。同一分组内的节点会打进同一个 chunk不同分组则各自独立懒加载。5.2 默认分组与 loader 的取舍源码 constants.ts 定义的默认分组为export const defaultCodeSplitGroupings [ [component], [errorComponent], [notFoundComponent], ]即默认把component、errorComponent、notFoundComponent各自拆成独立 chunk而loader默认不分割——loader 本身是异步函数再拆一个 chunk 会造成「先拉 chunk、再执行 loader」的双重异步开销。只有确实需要时才把loader放入分组如上例 dashboard。5.3 其他子选项splitBehavior: ({ routeId }) CodeSplitGroupings | undefined按routeId编程式决定每个路由的分割方式返回值会被 router-code-splitter-plugin.ts 用同一套 schema 校验非法分组会抛错deleteNodes: Arrayloader | component | ...从路由中删除指定节点用于某些特殊场景addHmr: boolean默认true非生产环境是否为分割后的路由注入 HMR 处理。5.4 关键提醒不要混用手动懒加载开启autoCodeSplitting后插件会在构建期自动改写你的路由文件不要再手写createLazyRoute或lazyRouteComponent// WRONG —— autoCodeSplitting 开启时手动懒加载 const LazyAbout lazyRouteComponent(() import(./about)) // CORRECT —— 正常写路由文件即可插件负责分割 // src/routes/about.tsx export const Route createFileRoute(/about)({ component: AboutPage, }) function AboutPage() { return h1About/h1 }六、虚拟路由配置virtualRouteConfig除文件路由外插件还支持以编程方式传入虚拟路由树import { routes } from ./routes tanstackRouter({ target: react, virtualRouteConfig: routes, // 或直接传 ./routes.ts 字符串路径 })virtualRouteConfig可接受一个路由配置数组或指向配置文件的路径字符串适合路由由代码/服务端动态产出的场景。更完整的编程式路由树用法可参考 virtual-file-routes 技能文档。七、工作原理三个子插件的协作组合插件composed plugin的装配逻辑位于 router-composed-plugin.tsconst result [ { name: tanstack:router-inline-css-defaults, ... }, // 内联 CSS 默认 define ...routerGenerator, // ① 路由生成器始终存在 ] if (userConfig.autoCodeSplitting) { result.push(...routerCodeSplitter) // ② 代码分割器可选 } if (!isProduction !userConfig.autoCodeSplitting) { result.push(...routerHmr) // ③ HMR开发态、分割关闭时 }Route Generator始终启用由 router-generator-plugin.ts 实现基于tanstack/router-generator的Generator实例监听路由目录并生成routeTree.gen.ts。Vite 下在configResolved阶段初始化并首次生成之后通过watchChange钩子按create/update/delete事件增量生成Webpack/Rspack 下额外用chokidar监听路由目录——注释明确说明「webpack/rspack 的 watcher 不会注册新建文件」因此必须自己补一个文件监听来处理新增路由。插件在入口处声明enforce: pre确保在框架插件之前运行。Code SplitterautoCodeSplitting: true时启用由 router-code-splitter-plugin.ts 实现内部再拆成三个 transform 插件compile-reference-file编译原始路由文件检测分组并产出引用文件compile-virtual-file处理以?tsr-split为标识的虚拟模块按分组生成懒加载 chunkcompile-shared-file处理?tsr-shared标识的共享模块抽出多个分组共用的绑定sharedBindingsMap在编译间传递。虚拟模块标识常量定义于 constants.tstsrSplit tsr-split、tsrShared tsr-shared。HMR开发态且未开启分割时启用由 router-hmr-plugin.ts 实现向路由文件注入createRouteHmrStatement的 HMR 处理语句开启分割后 HMR 由 code splitter 自身接管addHmr默认开启。7.1 插件顺序的源码级校验值得注意的是code splitter 并不只依赖「约定」还会在 ViteconfigResolved阶段主动校验插件顺序若检测到vitejs/plugin-react、vitejs/plugin-react-swc、vitejs/plugin-react-oxc或vite-plugin-solid排在 router 插件之前会直接抛出Plugin order error并给出修正后的配置示例见 router-code-splitter-plugin.ts。因此在较新版本中「顺序错误静默失败」已升级为「构建期显式报错」更易排查。八、按需使用独立子插件Vite 入口vite.ts除组合插件外还导出各子插件适合只想用其中一部分能力的进阶场景import { tanstackRouter, // 组合插件默认推荐 tanstackRouterGenerator, // 仅路由生成 tanStackRouterCodeSplitter, // 仅代码分割 } from tanstack/router-plugin/vite注意tanStackRouterCodeSplitter依赖生成器产出的routesByFile映射routerPluginContext独立使用时需保证生成器同时运行TanStackRouterVite为已弃用的旧名称请使用tanstackRouter。九、路由重构工作流Route Refactor Workflow移动、重命名、新增或删除文件路由时按以下流程操作只改源文件在routesDirectory下修改路由文件保持导出的路由标识符名为Route重新生成让插件自动重新生成路由树若项目使用 CLI可运行pnpm exec tsr generate手动触发审查生成 diff检查生成的routeTree.gen.tsdiff 是否符合预期的 route ID、父路由、路径与 import。永远不要手工修复routeTree.gen.ts同步外围引用更新指向旧路由的链接、redirect、from类型收窄、params、preload 调用及相关测试跑完整验证运行路由生成测试、类型测试与生产构建。编辑器类型检查通过 ≠ 插件正确生成了新路由必须以构建产物为准。routeTree.gen.ts是运行时实际使用的生成源码应当提交进版本库。十、常见错误与排查10.1 CRITICALVite 配置中插件顺序错误router 插件必须位于框架插件之前否则路由生成与代码分割会失败新版会在构建期显式抛错见 7.1// WRONG —— react() 在 tanstackRouter() 之前 plugins: [react(), tanstackRouter({ target: react })] // CORRECT —— tanstackRouter() 在前 plugins: [tanstackRouter({ target: react }), react()]10.2 HIGH非 React 框架未指定 targettarget默认是reactSolid 或 Vue 必须显式指定否则生成的 import 与分割逻辑全部错乱// WRONG for Solid —— 会生成 React 的 import tanstackRouter({ autoCodeSplitting: true }) // CORRECT for Solid tanstackRouter({ target: solid, autoCodeSplitting: true })10.3 MEDIUM混淆 autoCodeSplitting 与手动懒加载开启autoCodeSplitting后插件会在构建期自动改写路由文件不需要也不应该手动createLazyRoute/lazyRouteComponent详见 5.4 的示例对比。10.4 HIGH手动编辑生成的路由树对routeTree.gen.ts的任何手改都会在下次生成时被覆盖并可能导致源路由、生成类型与运行时路由三者失步。正确做法是修正路由文件名或插件配置 → 重新生成 → 审查 diff。十一、延伸阅读router-core/code-splitting 技能文档手动代码分割概念、.lazy.tsx约定与getRouteApi用法与本文的autoCodeSplitting互为补充virtual-file-routes 技能文档编程式路由树与virtualRouteConfig的完整用法源码参考组合插件装配、配置 schema、代码分割实现、路由生成实现、HMR 实现、Vite 入口与独立导出。【免费下载链接】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),仅供参考
返回列表