@tanstack/router-plugin
Version:
Modern and scalable routing for React applications
237 lines (183 loc) • 8.32 kB
Markdown
---
name: router-plugin
description: >-
TanStack Router bundler plugin for route generation and automatic
code splitting. Supports Vite, Webpack, Rspack, and esbuild.
Configures autoCodeSplitting, routesDirectory, target framework,
and code split groupings.
type: core
library: tanstack-router
library_version: '1.166.2'
sources:
- TanStack/router:packages/router-plugin/src
- TanStack/router:docs/router/routing/file-based-routing.md
- TanStack/router:docs/router/guide/code-splitting.md
---
# Router Plugin (`/router-plugin`)
Bundler plugin that powers TanStack Router's file-based routing and automatic code splitting. Works with Vite, Webpack, Rspack, and esbuild via unplugin.
> **CRITICAL**: The router plugin MUST come before the framework plugin (React, Solid, Vue) in the Vite config. Wrong order causes route generation and code splitting to fail silently.
## Install
```bash
npm install -D /router-plugin
```
## Bundler Setup
### Vite (most common)
```ts
// 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(),
],
})
```
### Webpack
```ts
// webpack.config.js
const { tanstackRouter } = require('/router-plugin/webpack')
module.exports = {
plugins: [
tanstackRouter({
target: 'react',
autoCodeSplitting: true,
}),
],
}
```
### Rspack
```ts
// rspack.config.js
const { tanstackRouter } = require('/router-plugin/rspack')
module.exports = {
plugins: [
tanstackRouter({
target: 'react',
autoCodeSplitting: true,
}),
],
}
```
### esbuild
```ts
import { tanstackRouter } from '@tanstack/router-plugin/esbuild'
import esbuild from 'esbuild'
esbuild.build({
plugins: [
tanstackRouter({
target: 'react',
autoCodeSplitting: true,
}),
],
})
```
## Configuration Options
### Core Options
| Option | Type | Default | Description |
| ----------------------- | ----------------------------- | -------------------------- | ------------------------------------------ |
| `target` | `'react' \| 'solid' \| 'vue'` | `'react'` | Target framework |
| `routesDirectory` | `string` | `'./src/routes'` | Directory containing route files |
| `generatedRouteTree` | `string` | `'./src/routeTree.gen.ts'` | Path for generated route tree |
| `autoCodeSplitting` | `boolean` | `undefined` | Enable automatic code splitting |
| `enableRouteGeneration` | `boolean` | `true` | Set to `false` to disable route generation |
### File Convention Options
| Option | Type | Default | Description |
| ------------------------ | ------------------------------------------------------- | ----------- | ------------------------------------ |
| `routeFilePrefix` | `string` | `undefined` | Prefix filter for route files |
| `routeFileIgnorePrefix` | `string` | `'-'` | Prefix to exclude files from routing |
| `routeFileIgnorePattern` | `string` | `undefined` | Pattern to exclude from routing |
| `indexToken` | `string \| RegExp \| { regex: string; flags?: string }` | `'index'` | Token identifying index routes |
| `routeToken` | `string \| RegExp \| { regex: string; flags?: string }` | `'route'` | Token identifying route config files |
### Code Splitting Options
```ts
tanstackRouter({
target: 'react',
autoCodeSplitting: true,
codeSplittingOptions: {
// Default groupings for all routes
defaultBehavior: [['component'], ['errorComponent'], ['notFoundComponent']],
// Per-route custom splitting
splitBehavior: ({ routeId }) => {
if (routeId === '/dashboard') {
// Keep loader and component together for dashboard
return [['loader', 'component'], ['errorComponent']]
}
// Return undefined to use defaultBehavior
},
},
})
```
### Output Options
| Option | Type | Default | Description |
| --------------------------- | ---------------------- | ----------- | -------------------------------------------- |
| `quoteStyle` | `'single' \| 'double'` | `'single'` | Quote style in generated code |
| `semicolons` | `boolean` | `false` | Use semicolons in generated code |
| `disableTypes` | `boolean` | `false` | Disable TypeScript types |
| `disableLogging` | `boolean` | `false` | Suppress plugin logs |
| `addExtensions` | `boolean \| string` | `false` | Add file extensions to imports |
| `enableRouteTreeFormatting` | `boolean` | `true` | Format generated route tree |
| `verboseFileRoutes` | `boolean` | `undefined` | When `false`, auto-imports `createFileRoute` |
### Virtual Route Config
```ts
import { routes } from './routes'
tanstackRouter({
target: 'react',
virtualRouteConfig: routes, // or './routes.ts'
})
```
## How It Works
The composed plugin assembles up to 4 sub-plugins:
1. **Route Generator** (always) — Watches route files and generates `routeTree.gen.ts`
2. **Code Splitter** (when `autoCodeSplitting: true`) — Splits route files into lazy-loaded chunks using virtual modules
3. **Auto-Import** (when `verboseFileRoutes: false`) — Auto-injects `createFileRoute` imports
4. **HMR** (dev mode, when code splitter is off) — Hot-reloads route changes without full refresh
## Individual Plugin Exports
For advanced use, each sub-plugin is exported separately from the Vite entry:
```ts
import {
tanstackRouter, // Composed (default)
tanstackRouterGenerator, // Generator only
tanStackRouterCodeSplitter, // Code splitter only
tanstackRouterAutoImport, // Auto-import only
} from '/router-plugin/vite'
```
## Common Mistakes
### 1. CRITICAL: Wrong plugin order in Vite config
The router plugin must come before the framework plugin. Otherwise, route generation and code splitting fail silently.
```ts
// WRONG — react() before tanstackRouter()
plugins: [react(), tanstackRouter({ target: 'react' })]
// CORRECT — tanstackRouter() first
plugins: [tanstackRouter({ target: 'react' }), react()]
```
### 2. HIGH: Missing target option for non-React frameworks
The `target` defaults to `'react'`. For Solid or Vue, you must set it explicitly.
```ts
// WRONG for Solid — generates React imports
tanstackRouter({ autoCodeSplitting: true })
// CORRECT for Solid
tanstackRouter({ target: 'solid', autoCodeSplitting: true })
```
### 3. MEDIUM: Confusing autoCodeSplitting with manual lazy routes
When `autoCodeSplitting` is enabled, the plugin handles splitting automatically. You do NOT need manual `createLazyRoute` or `lazyRouteComponent` calls — the plugin transforms your route files at build time.
```tsx
// WRONG — manual lazy loading with autoCodeSplitting enabled
const LazyAbout = lazyRouteComponent(() => import('./about'))
// CORRECT — just write normal route files, plugin handles splitting
// src/routes/about.tsx
export const Route = createFileRoute('/about')({
component: AboutPage,
})
function AboutPage() {
return <h1>About</h1>
}
```
## Cross-References
- [router-core/code-splitting](../../../router-core/skills/router-core/code-splitting/SKILL.md) — manual code splitting concepts
- [virtual-file-routes](../../../virtual-file-routes/skills/virtual-file-routes/SKILL.md) — programmatic route trees