Framework
Version
Integrationen

Virtuelle Dateirouten

Wir danken dem Remix-Team für die Pionierarbeit beim Konzept der virtuellen Dateirouten. Wir haben uns von ihrer Arbeit inspirieren lassen und sie angepasst, um mit der bestehenden dateibasierten Routengenerierung von TanStack Router zu funktionieren.

Virtuelle Dateirouten sind ein mächtiges Konzept, das es Ihnen ermöglicht, einen Routenbaum programmatisch mit Code zu erstellen, der auf reale Dateien in Ihrem Projekt verweist. Dies kann nützlich sein, wenn

  • Sie bereits eine bestehende Routenorganisation haben, die Sie beibehalten möchten.
  • Sie den Speicherort Ihrer Routendateien anpassen möchten.
  • Sie die dateibasierte Routengenerierung von TanStack Router vollständig überschreiben und Ihre eigene Konvention erstellen möchten.

Hier ist ein kurzes Beispiel für die Verwendung von virtuellen Dateirouten, um einen Routenbaum auf eine Reihe von realen Dateien in Ihrem Projekt abzubilden

tsx
// routes.ts
import {
  rootRoute,
  route,
  index,
  layout,
  physical,
} from '@tanstack/virtual-file-routes'

export const routes = rootRoute('root.tsx', [
  index('index.tsx'),
  layout('pathlessLayout.tsx', [
    route('/dashboard', 'app/dashboard.tsx', [
      index('app/dashboard-index.tsx'),
      route('/invoices', 'app/dashboard-invoices.tsx', [
        index('app/invoices-index.tsx'),
        route('$id', 'app/invoice-detail.tsx'),
      ]),
    ]),
    physical('/posts', 'posts'),
  ]),
])
// routes.ts
import {
  rootRoute,
  route,
  index,
  layout,
  physical,
} from '@tanstack/virtual-file-routes'

export const routes = rootRoute('root.tsx', [
  index('index.tsx'),
  layout('pathlessLayout.tsx', [
    route('/dashboard', 'app/dashboard.tsx', [
      index('app/dashboard-index.tsx'),
      route('/invoices', 'app/dashboard-invoices.tsx', [
        index('app/invoices-index.tsx'),
        route('$id', 'app/invoice-detail.tsx'),
      ]),
    ]),
    physical('/posts', 'posts'),
  ]),
])

Konfiguration

Virtuelle Dateirouten können entweder konfiguriert werden über

  • Das TanStackRouter Plugin für Vite/Rspack/Webpack
  • Die tsr.config.json Datei für die TanStack Router CLI

Konfiguration über das TanStack Router Plugin

Wenn Sie das TanStackRouter Plugin für Vite/Rspack/Webpack verwenden, können Sie virtuelle Dateirouten konfigurieren, indem Sie den Pfad Ihrer Routendatei an die Option virtualRoutesConfig übergeben, wenn Sie das Plugin einrichten

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

export default defineConfig({
  plugins: [
    tanstackRouter({
      target: 'react',
      virtualRouteConfig: './routes.ts',
    }),
    react(),
  ],
})
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { tanstackRouter } from '@tanstack/router-plugin/vite'

export default defineConfig({
  plugins: [
    tanstackRouter({
      target: 'react',
      virtualRouteConfig: './routes.ts',
    }),
    react(),
  ],
})

Oder Sie wählen, die virtuellen Routen direkt in der Konfiguration zu definieren

tsx
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { tanstackRouter } from '@tanstack/router-plugin/vite'
import { rootRoute } from '@tanstack/virtual-file-routes'

const routes = rootRoute('root.tsx', [
  // ... the rest of your virtual route tree
])

export default defineConfig({
  plugins: [tanstackRouter({ virtualRouteConfig: routes }), react()],
})
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { tanstackRouter } from '@tanstack/router-plugin/vite'
import { rootRoute } from '@tanstack/virtual-file-routes'

const routes = rootRoute('root.tsx', [
  // ... the rest of your virtual route tree
])

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

Erstellen virtueller Dateirouten

Um virtuelle Dateirouten zu erstellen, müssen Sie das Paket @tanstack/virtual-file-routes importieren. Dieses Paket stellt eine Reihe von Funktionen bereit, mit denen Sie virtuelle Routen erstellen können, die auf reale Dateien in Ihrem Projekt verweisen. Einige Hilfsfunktionen werden aus dem Paket exportiert

  • rootRoute - Erstellt eine virtuelle Root-Route.
  • route - Erstellt eine virtuelle Route.
  • index - Erstellt eine virtuelle Index-Route.
  • layout - Erstellt eine virtuelle pfadlose Layout-Route.
  • physical - Erstellt eine physische virtuelle Route (mehr dazu später).

Virtuelle Root-Route

Die Funktion rootRoute wird verwendet, um eine virtuelle Root-Route zu erstellen. Sie nimmt einen Dateinamen und ein Array von Kind-Routen entgegen. Hier ist ein Beispiel für eine virtuelle Root-Route

tsx
// routes.ts
import { rootRoute } from '@tanstack/virtual-file-routes'

export const routes = rootRoute('root.tsx', [
  // ... children routes
])
// routes.ts
import { rootRoute } from '@tanstack/virtual-file-routes'

export const routes = rootRoute('root.tsx', [
  // ... children routes
])

Virtuelle Route

Die Funktion route wird verwendet, um eine virtuelle Route zu erstellen. Sie nimmt einen Pfad, einen Dateinamen und ein Array von Kind-Routen entgegen. Hier ist ein Beispiel für eine virtuelle Route

tsx
// routes.ts
import { route } from '@tanstack/virtual-file-routes'

export const routes = rootRoute('root.tsx', [
  route('/about', 'about.tsx', [
    // ... children routes
  ]),
])
// routes.ts
import { route } from '@tanstack/virtual-file-routes'

export const routes = rootRoute('root.tsx', [
  route('/about', 'about.tsx', [
    // ... children routes
  ]),
])

Sie können auch eine virtuelle Route ohne Dateinamen definieren. Dies ermöglicht es, ein gemeinsames Pfadpräfix für seine Kinder festzulegen

tsx
// routes.ts
import { route } from '@tanstack/virtual-file-routes'

export const routes = rootRoute('root.tsx', [
  route('/hello', [
    route('/world', 'world.tsx'), // full path will be "/hello/world"
    route('/universe', 'universe.tsx'), // full path will be "/hello/universe"
  ]),
])
// routes.ts
import { route } from '@tanstack/virtual-file-routes'

export const routes = rootRoute('root.tsx', [
  route('/hello', [
    route('/world', 'world.tsx'), // full path will be "/hello/world"
    route('/universe', 'universe.tsx'), // full path will be "/hello/universe"
  ]),
])

Virtuelle Index-Route

Die Funktion index wird verwendet, um eine virtuelle Index-Route zu erstellen. Sie nimmt einen Dateinamen entgegen. Hier ist ein Beispiel für eine virtuelle Index-Route

tsx
import { index } from '@tanstack/virtual-file-routes'

const routes = rootRoute('root.tsx', [index('index.tsx')])
import { index } from '@tanstack/virtual-file-routes'

const routes = rootRoute('root.tsx', [index('index.tsx')])

Virtuelle pfadlose Route

Die Funktion layout wird verwendet, um eine virtuelle pfadlose Route zu erstellen. Sie nimmt einen Dateinamen, ein Array von Kind-Routen und eine optionale pfadlose ID entgegen. Hier ist ein Beispiel für eine virtuelle pfadlose Route

tsx
// routes.ts
import { layout } from '@tanstack/virtual-file-routes'

export const routes = rootRoute('root.tsx', [
  layout('pathlessLayout.tsx', [
    // ... children routes
  ]),
])
// routes.ts
import { layout } from '@tanstack/virtual-file-routes'

export const routes = rootRoute('root.tsx', [
  layout('pathlessLayout.tsx', [
    // ... children routes
  ]),
])

Sie können auch eine pfadlose ID angeben, um der Route eine eindeutige Kennung zu geben, die sich vom Dateinamen unterscheidet

tsx
// routes.ts
import { layout } from '@tanstack/virtual-file-routes'

export const routes = rootRoute('root.tsx', [
  layout('my-pathless-layout-id', 'pathlessLayout.tsx', [
    // ... children routes
  ]),
])
// routes.ts
import { layout } from '@tanstack/virtual-file-routes'

export const routes = rootRoute('root.tsx', [
  layout('my-pathless-layout-id', 'pathlessLayout.tsx', [
    // ... children routes
  ]),
])

Physische virtuelle Routen

Physische virtuelle Routen sind eine Möglichkeit, ein Verzeichnis der guten alten TanStack Router dateibasierten Routing-Konvention unter einem bestimmten URL-Pfad zu "mounten". Dies kann nützlich sein, wenn Sie virtuelle Routen verwenden, um einen kleinen Teil Ihres Routenbaums weit oben in der Hierarchie anzupassen, aber die Standard-Dateibasierte Routing-Konvention für Unterrouten und Verzeichnisse verwenden möchten.

Betrachten Sie die folgende Dateistruktur

/routes
├── root.tsx
├── index.tsx
├── pathlessLayout.tsx
├── app
│   ├── dashboard.tsx
│   ├── dashboard-index.tsx
│   ├── dashboard-invoices.tsx
│   ├── invoices-index.tsx
│   ├── invoice-detail.tsx
└── posts
    ├── index.tsx
    ├── $postId.tsx
    ├── $postId.edit.tsx
    ├── comments/
    │   ├── index.tsx
    │   ├── $commentId.tsx
    └── likes/
        ├── index.tsx
        ├── $likeId.tsx
/routes
├── root.tsx
├── index.tsx
├── pathlessLayout.tsx
├── app
│   ├── dashboard.tsx
│   ├── dashboard-index.tsx
│   ├── dashboard-invoices.tsx
│   ├── invoices-index.tsx
│   ├── invoice-detail.tsx
└── posts
    ├── index.tsx
    ├── $postId.tsx
    ├── $postId.edit.tsx
    ├── comments/
    │   ├── index.tsx
    │   ├── $commentId.tsx
    └── likes/
        ├── index.tsx
        ├── $likeId.tsx

Verwenden wir virtuelle Routen, um unseren Routenbaum für alles außer posts anzupassen, und verwenden dann physische virtuelle Routen, um das Verzeichnis posts unter dem Pfad /posts zu mounten

tsx
// routes.ts
export const routes = rootRoute('root.tsx', [
  // Set up your virtual routes as normal
  index('index.tsx'),
  layout('pathlessLayout.tsx', [
    route('/dashboard', 'app/dashboard.tsx', [
      index('app/dashboard-index.tsx'),
      route('/invoices', 'app/dashboard-invoices.tsx', [
        index('app/invoices-index.tsx'),
        route('$id', 'app/invoice-detail.tsx'),
      ]),
    ]),
    // Mount the `posts` directory under the `/posts` path
    physical('/posts', 'posts'),
  ]),
])
// routes.ts
export const routes = rootRoute('root.tsx', [
  // Set up your virtual routes as normal
  index('index.tsx'),
  layout('pathlessLayout.tsx', [
    route('/dashboard', 'app/dashboard.tsx', [
      index('app/dashboard-index.tsx'),
      route('/invoices', 'app/dashboard-invoices.tsx', [
        index('app/invoices-index.tsx'),
        route('$id', 'app/invoice-detail.tsx'),
      ]),
    ]),
    // Mount the `posts` directory under the `/posts` path
    physical('/posts', 'posts'),
  ]),
])

Virtuelle Routen innerhalb des dateibasierten Routings von TanStack Router

Der vorherige Abschnitt zeigte Ihnen, wie Sie die dateibasierte Routing-Konvention von TanStack Router innerhalb einer virtuellen Routenkonfiguration verwenden können. Das Gegenteil ist jedoch auch möglich.
Sie können den Hauptteil des Routenbaums Ihrer App mit der dateibasierten Routing-Konvention von TanStack Router konfigurieren und für bestimmte Unterbäume die virtuelle Routenkonfiguration aktivieren.

Betrachten Sie die folgende Dateistruktur

/routes
├── __root.tsx
├── foo
│   ├── bar
│   │   ├── __virtual.ts
│   │   ├── details.tsx
│   │   ├── home.tsx
│   │   └── route.ts
│   └── bar.tsx
└── index.tsx
/routes
├── __root.tsx
├── foo
│   ├── bar
│   │   ├── __virtual.ts
│   │   ├── details.tsx
│   │   ├── home.tsx
│   │   └── route.ts
│   └── bar.tsx
└── index.tsx

Betrachten wir das Verzeichnis bar, das eine spezielle Datei namens __virtual.ts enthält. Diese Datei weist den Generator an, für dieses Verzeichnis (und seine Unterverzeichnisse) zur virtuellen Dateiroutenkonfiguration zu wechseln.

__virtual.ts konfiguriert die virtuellen Routen für diesen speziellen Teilbaum des Routenbaums. Es verwendet die gleiche API wie oben beschrieben, mit dem einzigen Unterschied, dass für diesen Teilbaum keine rootRoute definiert ist

tsx
// routes/foo/bar/__virtual.ts
import {
  defineVirtualSubtreeConfig,
  index,
  route,
} from '@tanstack/virtual-file-routes'

export default defineVirtualSubtreeConfig([
  index('home.tsx'),
  route('$id', 'details.tsx'),
])
// routes/foo/bar/__virtual.ts
import {
  defineVirtualSubtreeConfig,
  index,
  route,
} from '@tanstack/virtual-file-routes'

export default defineVirtualSubtreeConfig([
  index('home.tsx'),
  route('$id', 'details.tsx'),
])

Die Hilfsfunktion defineVirtualSubtreeConfig ist eng an Vite's defineConfig angelehnt und ermöglicht es Ihnen, eine Teilbaumkonfiguration über einen Standardexport zu definieren. Der Standardexport kann entweder sein

  • ein Teilbaum-Konfigurationsobjekt
  • eine Funktion, die ein Teilbaum-Konfigurationsobjekt zurückgibt
  • eine asynchrone Funktion, die ein Teilbaum-Konfigurationsobjekt zurückgibt

Inception

Sie können die dateibasierte Routing-Konvention von TanStack Router und die virtuelle Routenkonfiguration beliebig mischen und anpassen.
Lassen Sie uns tiefer eintauchen!
Schauen Sie sich das folgende Beispiel an, das mit der dateibasierten Routing-Konvention beginnt, dann für /posts zur virtuellen Routenkonfiguration wechselt, dann für /posts/lets-go zur dateibasierten Routing-Konvention zurückkehrt, nur um dann für /posts/lets-go/deeper erneut zur virtuellen Routenkonfiguration zu wechseln.

├── __root.tsx
├── index.tsx
├── posts
│   ├── __virtual.ts
│   ├── details.tsx
│   ├── home.tsx
│   └── lets-go
│       ├── deeper
│       │   ├── __virtual.ts
│       │   └── home.tsx
│       └── index.tsx
└── posts.tsx
├── __root.tsx
├── index.tsx
├── posts
│   ├── __virtual.ts
│   ├── details.tsx
│   ├── home.tsx
│   └── lets-go
│       ├── deeper
│       │   ├── __virtual.ts
│       │   └── home.tsx
│       └── index.tsx
└── posts.tsx

Konfiguration über die TanStack Router CLI

Wenn Sie die TanStack Router CLI verwenden, können Sie virtuelle Dateirouten konfigurieren, indem Sie den Pfad zu Ihrer Routendatei in der Datei tsr.config.json definieren

json
// tsr.config.json
{
  "virtualRouteConfig": "./routes.ts"
}
// tsr.config.json
{
  "virtualRouteConfig": "./routes.ts"
}

Oder Sie können die virtuellen Routen direkt in der Konfiguration definieren. Das ist zwar deutlich seltener, ermöglicht es Ihnen aber, sie über die TanStack Router CLI zu konfigurieren, indem Sie ein virtualRouteConfig Objekt zu Ihrer tsr.config.json Datei hinzufügen und Ihre virtuellen Routen definieren und den resultierenden JSON-Code übergeben, der durch den Aufruf der eigentlichen rootRoute/route/index/etc Funktionen aus dem Paket @tanstack/virtual-file-routes generiert wird

json
// tsr.config.json
{
  "virtualRouteConfig": {
    "type": "root",
    "file": "root.tsx",
    "children": [
      {
        "type": "index",
        "file": "home.tsx"
      },
      {
        "type": "route",
        "file": "posts/posts.tsx",
        "path": "/posts",
        "children": [
          {
            "type": "index",
            "file": "posts/posts-home.tsx"
          },
          {
            "type": "route",
            "file": "posts/posts-detail.tsx",
            "path": "$postId"
          }
        ]
      },
      {
        "type": "layout",
        "id": "first",
        "file": "layout/first-pathless-layout.tsx",
        "children": [
          {
            "type": "layout",
            "id": "second",
            "file": "layout/second-pathless-layout.tsx",
            "children": [
              {
                "type": "route",
                "file": "a.tsx",
                "path": "/route-a"
              },
              {
                "type": "route",
                "file": "b.tsx",
                "path": "/route-b"
              }
            ]
          }
        ]
      }
    ]
  }
}
// tsr.config.json
{
  "virtualRouteConfig": {
    "type": "root",
    "file": "root.tsx",
    "children": [
      {
        "type": "index",
        "file": "home.tsx"
      },
      {
        "type": "route",
        "file": "posts/posts.tsx",
        "path": "/posts",
        "children": [
          {
            "type": "index",
            "file": "posts/posts-home.tsx"
          },
          {
            "type": "route",
            "file": "posts/posts-detail.tsx",
            "path": "$postId"
          }
        ]
      },
      {
        "type": "layout",
        "id": "first",
        "file": "layout/first-pathless-layout.tsx",
        "children": [
          {
            "type": "layout",
            "id": "second",
            "file": "layout/second-pathless-layout.tsx",
            "children": [
              {
                "type": "route",
                "file": "a.tsx",
                "path": "/route-a"
              },
              {
                "type": "route",
                "file": "b.tsx",
                "path": "/route-b"
              }
            ]
          }
        ]
      }
    ]
  }
}
Unsere Partner
Code Rabbit
Netlify
Neon
Clerk
Convex
Sentry
Bytes abonnieren

Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.

Bytes

Kein Spam. Jederzeit kündbar.

Bytes abonnieren

Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.

Bytes

Kein Spam. Jederzeit kündbar.