尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

@tanstack/router-plugin 深度解析:面向 Vite/Webpack/Rspack/esbuild 的路由生成与自动代码分割插件

@tanstack/router-plugin 深度解析:面向 Vite/Webpack/Rspack/esbuild 的路由生成与自动代码分割插件 tanstack/router-plugin 深度解析面向 Vite/Webpack/Rspack/esbuild 的路由生成与自动代码分割插件【免费下载链接】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/routertanstack/router-plugin是 TanStack Router 生态中的构建期 Bundler 插件负责文件路由file-based routing的自动生成与按路由代码分割automatic code splitting通过 unplugin 统一支持 Vite、Webpack、Rspack 与 esbuild。本文以仓库中 router-plugin 技能规格 及其配套的 SKILL.md 为主体结合 插件源码 与真实示例配置系统讲解插件的安装接入、全部配置项、底层工作原理、路由重构工作流以及高频失败模式帮助你正确配置并避开常见陷阱。插件定位与解决的核心问题在纯手写路由的应用中每新增一个路由文件都需要手动维护路由树、编写createFileRoute与懒加载引用极易出现路径拼写错误、类型不匹配或遗漏代码分割。tanstack/router-plugin将这一过程自动化路由生成持续监听routesDirectory默认./src/routes下的文件自动生成路由树文件routeTree.gen.ts自动代码分割开启autoCodeSplitting后构建期自动把路由组件、loader、错误组件等拆分为懒加载 chunk无需手写lazyRouteComponent跨框架支持通过target指定react | solid | vue生成对应框架的导入代码跨 Bundler 支持基于 unplugin 的统一抽象同一份插件代码可适配 Vite、Webpack、Rspack 与 esbuild。从包的 exports 字段 可以看出它对外暴露了tanstack/router-plugin/vite、/webpack、/rspack、/esbuild与/context五个子路径各 Bundler 使用各自的入口这是本插件最基本的使用约束。技能规格表中将“使用错误的插件导出入口”列为 HIGH 优先级失败模式其机制正是每个 Bundler 有独立导出如TanStackRouterVite、TanStackRouterWebpack选错入口会导致构建失败。安装与各 Bundler 接入方式插件作为开发依赖安装npm install -D tanstack/router-pluginVite最常见// 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(), ], })仓库中真实的 basic-file-based 示例 采用完全一致的写法tailwindcss()、tanstackRouter({ target: react, autoCodeSplitting: true })、react()依次排列。注意插件顺序——路由插件必须位于框架插件之前否则路由生成与代码分割会静默失败。Webpack// webpack.config.js const { tanstackRouter } require(tanstack/router-plugin/webpack) module.exports { plugins: [ tanstackRouter({ target: react, autoCodeSplitting: true, }), ], }Rspack// rspack.config.js const { tanstackRouter } require(tanstack/router-plugin/rspack) module.exports { plugins: [ tanstackRouter({ target: react, autoCodeSplitting: true, }), ], }esbuildimport { tanstackRouter } from tanstack/router-plugin/esbuild import esbuild from esbuild esbuild.build({ plugins: [ tanstackRouter({ target: react, autoCodeSplitting: true, }), ], })配置项全解所有选项通过 zod 校验 统一解析核心选项中的routesDirectory、generatedRouteTree等继承自tanstack/router-generator的配置 schema插件在其上扩展了enableRouteGeneration、codeSplittingOptions与pluginHMR 风格、Vite 环境名。核心选项选项类型默认值说明targetreact \| solid \| vuereact目标框架决定生成的路由代码使用哪个框架的 APIroutesDirectorystring./src/routes存放路由文件的目录generatedRouteTreestring./src/routeTree.gen.ts生成路由树的输出路径autoCodeSplittingbooleanundefined是否启用自动代码分割enableRouteGenerationbooleantrue设为false可关闭路由生成从 router-generator-plugin.ts 的源码可见enableRouteGeneration false时generate直接返回路由文件不再被监听生成而routesDirectory若为相对路径会被拼接在构建根目录process.cwd()或 Vite 的config.root之后因此配置错误路径会导致“路由缺失或路由树陈旧”。文件约定选项选项类型默认值说明routeFilePrefixstringundefined仅匹配该前缀的路由文件routeFileIgnorePrefixstring-以此前缀开头的文件被排除出路由routeFileIgnorePatternstringundefined匹配该模式的文件被排除出路由indexTokenstring \| RegExp \| { regex: string; flags?: string }index标识 index 路由的 tokenrouteTokenstring \| RegExp \| { regex: string; flags?: string }route标识路由配置文件的 token这些选项直接控制路由文件的“识别规则”。例如利用routeFileIgnorePrefix把组件、工具函数等非路由文件放在以-开头的目录中它们就不会被误判为路由routeToken则用于识别如about.route.tsx这类带配置性质的路由文件。代码分割选项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 }, }, })源码 config.ts 对分组做了严格的 zod 校验分组必须是「数组的数组」合法成员仅限loader、component、pendingComponent、errorComponent、notFoundComponent五个节点且同一节点不得重复出现例如[[component], [component, loader]]会被拒绝。defaultBehavior的默认值是[[component],[pendingComponent],[errorComponent],[notFoundComponent]]即每个节点单独拆包splitBehavior接收{ routeId }参数并按返回的分组覆盖默认行为。此外codeSplittingOptions还支持deleteNodes从路由中删除指定节点与addHmr默认true在分割模式下注入 HMR 逻辑。输出选项选项类型默认值说明quoteStylesingle \| doublesingle生成代码中字符串的引号风格semicolonsbooleanfalse生成代码是否使用分号disableTypesbooleanfalse关闭生成的 TypeScript 类型disableLoggingbooleanfalse关闭插件日志addExtensionsboolean \| stringfalse为 import 补充文件扩展名enableRouteTreeFormattingbooleantrue是否格式化生成的路由树这些选项影响routeTree.gen.ts的代码风格。例如在 ESM/NodeNext 环境下可将addExtensions设为true或.js等具体扩展名以解决 import 路径缺少扩展名的模块解析问题。虚拟路由配置不依赖文件系统而是以代码声明路由树时使用import { routes } from ./routes tanstackRouter({ target: react, virtualRouteConfig: routes, // 或 ./routes.ts })virtualRouteConfig可接受路由定义对象或指向定义文件的字符串路径与文件路由互斥适合需要以编程方式而非文件名约定构建路由树的场景。工作原理三个子插件的组装从 router-composed-plugin.ts 的源码可以看到tanstackRouter()组合插件按条件组装若干子插件内联 CSS 默认定义插件恒存在为所有 Bundler 注入TSS_INLINE_CSS_ENABLED环境变量默认值Vite 走defineWebpack/Rspack 走DefinePluginesbuild 走options.define用于控制内联 CSS 开关路由生成器恒存在基于tanstack/router-generator的Generator类实例化Vite 下在configResolved时初始化并执行首次生成随后通过watchChange监听路由文件的 create/update/delete 事件增量重生成Webpack/Rspack 下则在beforeRun/watchRun钩子中触发生成其中 Rspack 额外用 chokidar 弥补其 watcher 不注册新建文件的缺陷见 router-generator-plugin.ts代码分割器当autoCodeSplitting: true通过虚拟模块virtual modules把路由文件拆成懒加载 chunkHMR 插件开发模式且未开启代码分割时以不刷新页面的方式热更新路由变更。对应 vite.ts 的导出tanstackRouter为组合插件默认tanstackRouterGenerator为仅生成器tanStackRouterCodeSplitter为仅分割器旧名称TanStackRouterVite已被标记为 deprecated 并建议改用tanstackRouter。HMR 风格还可在plugin.hmr.style中显式选择viteESMimport.meta.hot或webpackimport.meta.webpackHot供 webpack/Rspack 入口使用。路由重构工作流当需要移动、重命名、新增或删除文件路由时遵循以下流程可避免路由树与源码失步修改routesDirectory下的源文件保持导出的路由标识符名为Route让插件自动重新生成路由树若项目使用 CLI也可执行pnpm exec tsr generate检查生成 diff 中预期的 route id、父子关系、路径与 import——绝不要手工修补routeTree.gen.ts同步更新引用旧路由的链接、重定向、from类型收窄、参数、preload 调用与测试运行路由生成测试、类型测试与生产构建。仅编辑器类型检查通过并不能证明插件正确生成或分割了新路由。routeTree.gen.ts属于“生成源码”应用运行时直接使用应当提交到版本库。高频失败模式与规避方法技能规格 skill_spec.md 登记了 3 个失败模式2 个 HIGH、1 个 MEDIUMSKILL.md 则补充了第 4 个常见错误逐一说明1. CRITICALVite 配置中插件顺序错误路由插件必须位于框架插件之前否则路由生成与代码分割静默失败// WRONG —— react() 在 tanstackRouter() 之前 plugins: [react(), tanstackRouter({ target: react })] // CORRECT —— tanstackRouter() 在前 plugins: [tanstackRouter({ target: react }), react()]2. HIGH非 React 框架漏配 targettarget默认是react使用 Solid 或 Vue 时必须显式指定// 对 Solid 来说是错误的 —— 会生成 React 导入 tanstackRouter({ autoCodeSplitting: true }) // Solid 正确写法 tanstackRouter({ target: solid, autoCodeSplitting: true })3. MEDIUM把 autoCodeSplitting 与手动懒加载混用开启autoCodeSplitting后插件在构建期自动转换路由文件不需要手动调用createLazyRoute或lazyRouteComponent// WRONG —— 开启自动分割后仍手动懒加载 const LazyAbout lazyRouteComponent(() import(./about)) // CORRECT —— 正常编写路由文件插件负责分割 // src/routes/about.tsx export const Route createFileRoute(/about)({ component: AboutPage, }) function AboutPage() { return h1About/h1 }4. HIGH手工编辑生成的路由树对routeTree.gen.ts的任何手工修改都会被重新生成覆盖并使源路由、生成类型与运行时路由三者失步。正确做法是修正路由文件名或插件配置重新生成并核对 diff。与周边模块的关系插件依赖tanstack/router-generator路由树生成核心、tanstack/router-core路由运行时类型与tanstack/router-utils共享工具运行时侧的手动分割概念可参考 router-core 的 code-splitting 技能编程式路由树则参考 virtual-file-routes 技能。在仓库的 e2e 测试集 中basic-file-based、basic-esbuild-file-based、rspack-basic-file-based等用例分别验证了插件在 Vite/esbuild/Rspack 下的真实构建链路是理解插件行为最直接的实验依据。小结tanstack/router-plugin把 TanStack Router 的两项核心 DX——文件路由自动生成与自动代码分割——下沉到构建期完成。掌握三点即可稳定落地按 Bundler 选择正确导出入口、保持路由插件在框架插件之前、永不手工修改生成的路由树。在此基础上善用codeSplittingOptions的分组定制与target/routesDirectory/generatedRouteTree等配置即可在 React、Solid、Vue 与多 Bundler 环境中获得一致的类型安全路由体验。【免费下载链接】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),仅供参考
返回列表