Skip to main content

Vite Plugin

Vite plugin for TanStack Router with automatic route generation, code splitting, and development features.

Installation

npm install @tanstack/router-plugin

Basic Usage

// vite.config.ts
import { defineConfig } from 'vite'
import { tanstackRouter } from '@tanstack/router-plugin/vite'

export default defineConfig({
  plugins: [
    tanstackRouter()
  ]
})

Configuration Options

routesDirectory
string
Directory containing route files.Default: './src/routes'
tanstackRouter({
  routesDirectory: './app/routes'
})
generatedRouteTree
string
Output path for generated route tree file.Default: './src/routeTree.gen.ts'
tanstackRouter({
  generatedRouteTree: './app/routeTree.gen.ts'
})
routeFileIgnorePrefix
string
Prefix to ignore when generating routes.Default: '-'
tanstackRouter({
  routeFileIgnorePrefix: '_'
})
Files starting with this prefix (e.g., _component.tsx) will be ignored.
routeFileIgnorePattern
RegExp
Pattern to ignore when generating routes.
tanstackRouter({
  routeFileIgnorePattern: /\.test\./
})
quoteStyle
'single' | 'double'
Quote style for generated code.Default: 'single'
tanstackRouter({
  quoteStyle: 'double'
})
semicolons
boolean
Whether to use semicolons in generated code.Default: false
tanstackRouter({
  semicolons: true
})
autoCodeSplitting
boolean
Enable automatic code splitting.Default: false
tanstackRouter({
  autoCodeSplitting: true
})
codeSplittingOptions
CodeSplittingOptions
Advanced code splitting configuration.
tanstackRouter({
  autoCodeSplitting: true,
  codeSplittingOptions: {
    defaultBehavior: [
      ['component'],
      ['pendingComponent', 'errorComponent']
    ]
  }
})
enableRouteGeneration
boolean
Enable/disable route generation.Default: true
tanstackRouter({
  enableRouteGeneration: false
})

Code Splitting Options

Configure how routes are split into separate chunks.
defaultBehavior
Array<Array<string>>
Default splitting strategy for all routes.Default: [['component'], ['pendingComponent'], ['errorComponent'], ['notFoundComponent']]
codeSplittingOptions: {
  // Split component and loader together
  defaultBehavior: [
    ['component', 'loader'],
    ['pendingComponent'],
    ['errorComponent']
  ]
}
splitBehavior
(params: { routeId: string }) => Array<Array<string>> | undefined
Custom splitting strategy per route.
codeSplittingOptions: {
  splitBehavior: ({ routeId }) => {
    // Don't split the index route
    if (routeId === '/') {
      return undefined
    }
    
    // Custom splitting for admin routes
    if (routeId.startsWith('/admin')) {
      return [
        ['component', 'loader', 'pendingComponent']
      ]
    }
    
    // Use default for others
    return undefined
  }
}
deleteNodes
Array<string>
Route properties to remove during splitting.
codeSplittingOptions: {
  deleteNodes: ['staticData', 'meta']
}
addHmr
boolean
Add Hot Module Replacement support.Default: true
codeSplittingOptions: {
  addHmr: false
}

Examples

Basic Setup

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { tanstackRouter } from '@tanstack/router-plugin/vite'

export default defineConfig({
  plugins: [
    react(),
    tanstackRouter()
  ]
})

Custom Routes Directory

import { tanstackRouter } from '@tanstack/router-plugin/vite'

export default defineConfig({
  plugins: [
    tanstackRouter({
      routesDirectory: './src/pages',
      generatedRouteTree: './src/pages/routeTree.gen.ts'
    })
  ]
})

With Code Splitting

import { tanstackRouter } from '@tanstack/router-plugin/vite'

export default defineConfig({
  plugins: [
    tanstackRouter({
      autoCodeSplitting: true,
      codeSplittingOptions: {
        // Split components and loaders separately
        defaultBehavior: [
          ['component'],
          ['loader'],
          ['pendingComponent', 'errorComponent']
        ]
      }
    })
  ]
})

Custom File Patterns

import { tanstackRouter } from '@tanstack/router-plugin/vite'

export default defineConfig({
  plugins: [
    tanstackRouter({
      routeFileIgnorePrefix: '_',
      routeFileIgnorePattern: /\.(test|spec)\./,
      quoteStyle: 'double',
      semicolons: true
    })
  ]
})

Per-Route Code Splitting

import { tanstackRouter } from '@tanstack/router-plugin/vite'

export default defineConfig({
  plugins: [
    tanstackRouter({
      autoCodeSplitting: true,
      codeSplittingOptions: {
        splitBehavior: ({ routeId }) => {
          // Don't split the root and index routes
          if (routeId === '__root__' || routeId === '/') {
            return undefined
          }
          
          // Split admin routes more aggressively
          if (routeId.startsWith('/admin')) {
            return [
              ['component'],
              ['loader'],
              ['beforeLoad'],
              ['pendingComponent'],
              ['errorComponent']
            ]
          }
          
          // Default splitting for other routes
          return [
            ['component', 'pendingComponent'],
            ['loader'],
            ['errorComponent']
          ]
        }
      }
    })
  ]
})

Monorepo Setup

import { defineConfig } from 'vite'
import { tanstackRouter } from '@tanstack/router-plugin/vite'
import path from 'path'

export default defineConfig({
  plugins: [
    tanstackRouter({
      routesDirectory: path.resolve(__dirname, './src/routes'),
      generatedRouteTree: path.resolve(__dirname, './src/routeTree.gen.ts')
    })
  ]
})

With Multiple Environments

import { defineConfig } from 'vite'
import { tanstackRouter } from '@tanstack/router-plugin/vite'

export default defineConfig(({ mode }) => ({
  plugins: [
    tanstackRouter({
      autoCodeSplitting: mode === 'production',
      codeSplittingOptions: {
        addHmr: mode === 'development'
      }
    })
  ]
}))

Generated Files

The plugin generates a routeTree.gen.ts file:
// routeTree.gen.ts (auto-generated)
import { Route as rootRoute } from './routes/__root'
import { Route as IndexRoute } from './routes/index'
import { Route as PostsRoute } from './routes/posts'
import { Route as PostsIndexRoute } from './routes/posts/index'
import { Route as PostsPostIdRoute } from './routes/posts/$postId'

export const routeTree = rootRoute.addChildren([
  IndexRoute,
  PostsRoute.addChildren([
    PostsIndexRoute,
    PostsPostIdRoute
  ])
])

File-Based Routing Conventions

src/routes/
  __root.tsx         -> / (root layout)
  index.tsx          -> / (index page)
  about.tsx          -> /about
  posts.tsx          -> /posts (layout)
  posts/
    index.tsx        -> /posts (index)
    $postId.tsx      -> /posts/:postId
    $postId/
      edit.tsx       -> /posts/:postId/edit
  _components/       -> Ignored (starts with _)
  -utils.ts          -> Ignored (starts with -)

TypeScript Support

The plugin automatically generates TypeScript types:
// Generated types are automatically picked up
import { Link } from '@tanstack/react-router'

// Full autocomplete for routes
<Link to="/posts/$postId" params={{ postId: '123' }} />

Hot Module Replacement

The plugin supports HMR for route updates:
  • Add/remove route files → route tree updates automatically
  • Edit route components → hot reload without full page refresh
  • Update route config → route tree regenerates

Troubleshooting

Routes Not Generating

Check that:
  • routesDirectory path is correct
  • Route files have proper extensions (.tsx, .ts)
  • Files don’t start with ignore prefix

Type Errors

Ensure:
  • Generated route tree file is in your tsconfig.json include
  • Router is properly registered in your app
// tsconfig.json
{
  "include": [
    "src/**/*",
    "src/routeTree.gen.ts" // Include generated file
  ]
}

Build docs developers (and LLMs) love