Deutsch

Erschließen Sie skalierbare und dynamische UIs in Next.js. Unser umfassender Leitfaden behandelt Route Groups zur Organisation und Parallel Routes für komplexe Dashboards. Werden Sie jetzt zum Experten!

Meistern des Next.js App Routers: Ein tiefer Einblick in die Architektur von Route Groups und Parallel Routes

Die Veröffentlichung des Next.js App Routers markierte einen Paradigmenwechsel in der Art und Weise, wie Entwickler Webanwendungen mit dem beliebten React-Framework erstellen. Der App Router entfernte sich von den dateibasierten Konventionen des Pages Routers und führte ein leistungsfähigeres, flexibleres und serverzentriertes Modell ein. Diese Entwicklung ermöglicht es uns, hochkomplexe und performante Benutzeroberflächen mit größerer Kontrolle und Organisation zu erstellen. Zu den transformativsten eingeführten Funktionen gehören Route Groups und Parallel Routes.

Für Entwickler, die Anwendungen auf Unternehmensebene erstellen möchten, ist die Beherrschung dieser beiden Konzepte nicht nur vorteilhaft – sie ist unerlässlich. Sie lösen gängige architektonische Herausforderungen im Zusammenhang mit dem Layout-Management, der Routenorganisation und der Erstellung dynamischer, mehrteiliger Benutzeroberflächen wie Dashboards. Dieser Leitfaden bietet eine umfassende Untersuchung von Route Groups und Parallel Routes, von grundlegenden Konzepten bis hin zu fortgeschrittenen Implementierungsstrategien und Best Practices für ein globales Entwicklerpublikum.

Den Next.js App Router verstehen: Eine kurze Auffrischung

Bevor wir uns den Details widmen, werfen wir einen kurzen Blick auf die Kernprinzipien des App Routers. Seine Architektur basiert auf einem verzeichnisbasierten System, in dem Ordner URL-Segmente definieren. Spezielle Dateien innerhalb dieser Ordner definieren die Benutzeroberfläche und das Verhalten für dieses Segment:

Diese Struktur, kombiniert mit der standardmäßigen Verwendung von React Server Components (RSCs), fördert einen Server-First-Ansatz, der die Leistung und Datenabrufmuster erheblich verbessern kann. Route Groups und Parallel Routes sind fortgeschrittene Konventionen, die auf diesem Fundament aufbauen.

Route Groups entmystifiziert: Organisation Ihres Projekts für Übersichtlichkeit und Skalierbarkeit

Wenn eine Anwendung wächst, kann die Anzahl der Routen unübersichtlich werden. Sie haben möglicherweise eine Reihe von Seiten für das Marketing, eine weitere für die Benutzerauthentifizierung und eine dritte für das Kern-Dashboard der Anwendung. Logisch gesehen sind dies separate Abschnitte, aber wie organisieren Sie sie in Ihrem Dateisystem, ohne Ihre URLs unübersichtlich zu machen? Genau dieses Problem lösen Route Groups.

Was sind Route Groups?

Eine Route Group ist ein Mechanismus, um Ihre Dateien und Routensegmente in logische Gruppen zu organisieren, ohne die URL-Struktur zu beeinflussen. Sie erstellen eine Route Group, indem Sie den Namen eines Ordners in Klammern setzen, zum Beispiel (marketing) oder (app).

Der Ordnername in den Klammern dient rein organisatorischen Zwecken. Next.js ignoriert ihn vollständig bei der Bestimmung des URL-Pfades. Zum Beispiel wird die Datei unter app/(marketing)/about/page.js unter der URL /about bereitgestellt, nicht unter /(marketing)/about.

Wichtige Anwendungsfälle und Vorteile von Route Groups

Während die einfache Organisation ein Vorteil ist, liegt die wahre Stärke von Route Groups in ihrer Fähigkeit, Ihre Anwendung in Abschnitte mit unterschiedlichen, gemeinsamen Layouts zu unterteilen.

1. Erstellen unterschiedlicher Layouts für Routensegmente

Dies ist der häufigste und leistungsstärkste Anwendungsfall. Stellen Sie sich eine Webanwendung mit zwei Hauptbereichen vor:

Ohne Route Groups wäre die Anwendung unterschiedlicher Root-Layouts auf diese Abschnitte komplex. Mit Route Groups ist es unglaublich intuitiv. Sie können eine eindeutige layout.js-Datei in jeder Gruppe erstellen.

Hier ist eine typische Dateistruktur für dieses Szenario:

app/
├── (marketing)/
│   ├── layout.js      // Öffentliches Layout mit Marketing-Kopf-/Fußzeile
│   ├── page.js        // Wird unter '/'
 gerendert│   └── about/
│       └── page.js    // Wird unter '/about'
 gerendert├── (app)/
│   ├── layout.js      // Dashboard-Layout mit Seitenleiste
│   ├── dashboard/
│   │   └── page.js    // Wird unter '/dashboard'
 gerendert│   └── settings/
│       └── page.js    // Wird unter '/settings' gerendert
└── layout.js          // Root-Layout (z.B. für <html>- und <body>-Tags)

In dieser Architektur:

2. Ein Segment aus einem gemeinsamen Layout ausschließen

Manchmal muss eine bestimmte Seite oder ein Abschnitt vollständig aus dem übergeordneten Layout ausbrechen. Ein gängiges Beispiel ist ein Bezahlvorgang oder eine spezielle Landing-Page, die nicht die Navigation der Hauptseite haben sollte. Sie können dies erreichen, indem Sie die Route in eine Gruppe platzieren, die das übergeordnete Layout nicht teilt. Obwohl dies komplex klingt, bedeutet es einfach, einer Routengruppe ein eigenes Top-Level-layout.js zu geben, das die `children` aus dem Root-Layout nicht rendert.

Praktisches Beispiel: Erstellen einer Anwendung mit mehreren Layouts

Lassen Sie uns eine minimale Version der oben beschriebenen Marketing/App-Struktur erstellen.

1. Das Root-Layout (app/layout.js)

Dieses Layout ist minimal und gilt für jede einzelne Seite. Es definiert die wesentliche HTML-Struktur.

// app/layout.js
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

2. Das Marketing-Layout (app/(marketing)/layout.js)

Dieses Layout enthält eine öffentlich zugängliche Kopf- und Fußzeile.

// app/(marketing)/layout.js
export default function MarketingLayout({ children }) {
  return (
    <div>
      <header>Marketing Header</header>
      <main>{children}</main>
      <footer>Marketing Footer</footer>
    </div>
  );
}

3. Das App-Dashboard-Layout (app/(app)/layout.js)

Dieses Layout hat eine andere Struktur und verfügt über eine Seitenleiste für authentifizierte Benutzer.

// app/(app)/layout.js
export default function AppLayout({ children }) {
  return (
    <div style={{ display: 'flex' }}>
      <aside style={{ width: '200px', borderRight: '1px solid #ccc' }}>
        Dashboard Sidebar
      </aside>
      <main style={{ flex: 1, padding: '20px' }}>{children}</main>
    </div>
  );
}

Mit dieser Struktur wird beim Navigieren zu /about die Seite mit dem `MarketingLayout` gerendert, während beim Navigieren zu /dashboard die Seite mit dem `AppLayout` gerendert wird. Die URL bleibt sauber und semantisch, während die Dateistruktur unseres Projekts perfekt organisiert und skalierbar ist.

Dynamische UIs mit Parallel Routes erschließen

Während Route Groups helfen, verschiedene Abschnitte einer Anwendung zu organisieren, lösen Parallel Routes eine andere Herausforderung: die Anzeige mehrerer, unabhängiger Seitenansichten innerhalb eines einzigen Layouts. Dies ist eine häufige Anforderung für komplexe Dashboards, Social-Media-Feeds oder jede Benutzeroberfläche, bei der verschiedene Panels gleichzeitig gerendert und verwaltet werden müssen.

Was sind Parallel Routes?

Parallel Routes ermöglichen es Ihnen, eine oder mehrere Seiten gleichzeitig innerhalb desselben Layouts zu rendern. Diese Routen werden mithilfe einer speziellen Ordnerkonvention namens Slots definiert. Slots werden mit der @folderName-Syntax erstellt. Sie sind nicht Teil der URL-Struktur; stattdessen werden sie automatisch als Props an die nächstgelegene gemeinsame übergeordnete `layout.js`-Datei übergeben.

Wenn Sie beispielsweise ein Layout haben, das einen Team-Aktivitäts-Feed und ein Analyse-Diagramm nebeneinander anzeigen muss, können Sie zwei Slots definieren: `@team` und `@analytics`.

Die Kernidee: Slots

Stellen Sie sich Slots als benannte Platzhalter in Ihrem Layout vor. Die Layout-Datei akzeptiert diese Slots explizit als Props und entscheidet, wo sie gerendert werden sollen.

Betrachten Sie diese Layout-Komponente:

// Ein Layout, das zwei Slots akzeptiert: 'team' und 'analytics'
export default function DashboardLayout({ children, team, analytics }) {
  return (
    <div>
      {children}
      <div style={{ display: 'flex' }}>
        {team}
        {analytics}
      </div>
    </div>
  );
}

Hier sind `children`, `team` und `analytics` allesamt Slots. `children` ist ein impliziter Slot, der der Standard-page.js im Verzeichnis entspricht. `team` und `analytics` sind explizite Slots, die mit dem `@`-Präfix im Dateisystem erstellt werden müssen.

Wichtige Funktionen und Vorteile

Ein praxisnahes Szenario: Erstellen eines komplexen Dashboards

Lassen Sie uns ein Dashboard unter der URL /dashboard entwerfen. Es wird einen Hauptinhaltsbereich, ein Team-Aktivitäts-Panel und ein Leistungsanalyse-Panel haben.

Dateistruktur:

app/
└── dashboard/
    ├── @analytics/
    │   ├── page.js          // UI für den Analytics-Slot
    │   └── loading.js     // Lade-UI speziell für Analytics
    ├── @team/
    │   └── page.js          // UI für den Team-Slot
    ├── layout.js            // Das Layout, das die Slots orchestriert
    └── page.js              // Der implizite 'children'-Slot (Hauptinhalt)

1. Das Dashboard-Layout (app/dashboard/layout.js)

Dieses Layout empfängt und ordnet die drei Slots an.

// app/dashboard/layout.js
export default function DashboardLayout({ children, analytics, team }) {
  const isLoggedIn = true; // Durch echte Authentifizierungslogik ersetzen

  return isLoggedIn ? (
    <div>
      <h1>Main Dashboard</h1>
      {children}
      <div style={{ marginTop: '20px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '20px' }}>
        <div style={{ border: '1px solid blue', padding: '10px' }}>
          <h2>Team Activity</h2>
          {team}
        </div>
        <div style={{ border: '1px solid green', padding: '10px' }}>
          <h2>Performance Analytics</h2>
          {analytics}
        </div>
      </div>
    </div>
  ) : (
    <div>Please log in to view the dashboard.</div>
  );
}

2. Die Slot-Seiten (z.B. app/dashboard/@analytics/page.js)

Die page.js-Datei jedes Slots enthält die Benutzeroberfläche für das jeweilige Panel.

// app/dashboard/@analytics/page.js
async function getAnalyticsData() {
  // Simuliert eine Netzwerkanfrage
  await new Promise(resolve => setTimeout(resolve, 3000));
  return { views: '1.2M', revenue: '$50,000' };
}

export default async function AnalyticsPage() {
  const data = await getAnalyticsData();
  return (
    <div>
      <p>Page Views: {data.views}</p>
      <p>Revenue: {data.revenue}</p>
    </div>
  );
}

// app/dashboard/@analytics/loading.js
export default function Loading() {
  return <p>Lade Analysedaten...</p>;
}

Mit diesem Setup rendert Next.js das `DashboardLayout`, wenn ein Benutzer zu /dashboard navigiert. Das Layout empfängt den gerenderten Inhalt von dashboard/page.js, dashboard/@team/page.js und dashboard/@analytics/page.js als Props und platziert sie entsprechend. Entscheidend ist, dass das Analyse-Panel seinen eigenen loading.js-Zustand für 3 Sekunden anzeigt, ohne das Rendern des restlichen Dashboards zu blockieren.

Umgang mit nicht übereinstimmenden Routen mit `default.js`

Eine entscheidende Frage stellt sich: Was passiert, wenn Next.js den aktiven Zustand eines Slots für die aktuelle URL nicht abrufen kann? Zum Beispiel könnte die URL bei einem ersten Laden oder einem Neuladen der Seite /dashboard sein, was keine spezifischen Anweisungen dafür gibt, was in den Slots @team oder `@analytics` angezeigt werden soll. Standardmäßig würde Next.js einen 404-Fehler rendern.

Um dies zu verhindern, können wir eine Fallback-UI bereitstellen, indem wir eine default.js-Datei innerhalb der parallelen Route erstellen.

Beispiel:

// app/dashboard/@analytics/default.js
export default function DefaultAnalyticsPage() {
  return (
    <div>
      <p>Keine Analysedaten ausgewählt.</p>
    </div>
  );
}

Wenn der Analytics-Slot nun nicht übereinstimmt, rendert Next.js den Inhalt von `default.js` anstelle einer 404-Seite. Dies ist unerlässlich, um eine reibungslose Benutzererfahrung zu schaffen, insbesondere beim erstmaligen Laden eines komplexen Setups mit parallelen Routen.

Kombination von Route Groups und Parallel Routes für fortgeschrittene Architekturen

Die wahre Stärke des App Routers wird erkannt, wenn man seine Funktionen kombiniert. Route Groups und Parallel Routes arbeiten wunderbar zusammen, um anspruchsvolle und hoch organisierte Anwendungsarchitekturen zu schaffen.

Anwendungsfall: Ein multimodaler Inhalts-Viewer

Stellen Sie sich eine Plattform wie eine Mediengalerie oder einen Dokumenten-Viewer vor, bei dem der Benutzer ein Element ansehen, aber auch ein modales Fenster öffnen kann, um dessen Details zu sehen, ohne den Kontext der Hintergrundseite zu verlieren. Dies wird oft als „Intercepting Route“ (abfangende Route) bezeichnet und ist ein leistungsstarkes Muster, das auf parallelen Routen basiert.

Lassen Sie uns eine Fotogalerie erstellen. Wenn Sie auf ein Foto klicken, öffnet es sich in einem Modal. Wenn Sie jedoch die Seite aktualisieren oder direkt zur URL des Fotos navigieren, sollte eine dedizierte Seite für dieses Foto angezeigt werden.

Dateistruktur:

app/
├── @modal/(..)(..)photos/[id]/page.js  // Die abgefangene Route für das Modal
├── photos/
│   └── [id]/
│       └── page.js                  // Die dedizierte Fotoseite
├── layout.js                        // Root-Layout, das den @modal-Slot empfängt
└── page.js                          // Die Hauptgalerieseite

Erklärung:

Dieses Muster kombiniert parallele Routen (den `@modal`-Slot) mit fortgeschrittenen Routing-Konventionen, um eine nahtlose Benutzererfahrung zu schaffen, die manuell nur sehr komplex zu implementieren wäre.

Best Practices und häufige Fallstricke

Best Practices für Route Groups

Best Practices für Parallel Routes

Häufige Fallstricke, die zu vermeiden sind

Fazit: Die Zukunft der Webanwendungen gestalten

Der Next.js App Router bietet mit Funktionen wie Route Groups und Parallel Routes eine robuste und skalierbare Grundlage für die moderne Webentwicklung. Route Groups bieten eine elegante Lösung zur Organisation von Code und zur Anwendung unterschiedlicher Layouts, ohne die URL-Semantik zu beeinträchtigen. Parallel Routes ermöglichen die Erstellung dynamischer, mehrteiliger Benutzeroberflächen mit unabhängigen Zuständen, was bisher nur durch komplexes clientseitiges Zustandsmanagement erreichbar war.

Durch das Verständnis und die Kombination dieser leistungsstarken Architekturmuster können Sie über einfache Websites hinausgehen und anspruchsvolle, performante und wartbare Anwendungen erstellen, die den Anforderungen der heutigen Benutzer gerecht werden. Die Lernkurve mag steiler sein als beim klassischen Pages Router, aber der Gewinn in Bezug auf Anwendungsarchitektur und Benutzererfahrung ist immens. Beginnen Sie, mit diesen Konzepten in Ihrem nächsten Projekt zu experimentieren, und schöpfen Sie das volle Potenzial von Next.js aus.

Meistern des Next.js App Routers: Ein tiefer Einblick in die Architektur von Route Groups und Parallel Routes | MLOG