> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# SPAs mit Inertia.js entwickeln

> Vorstellung von Inertia.js v3, das ein Laravel-Backend mit einem Vue-/React-/Svelte-Frontend verbindet. Praxisnahe Erläuterung – vom Mechanismus für SPAs ohne API bis zu Page-Komponenten, Shared Data und Formularverarbeitung.

## Was ist Inertia.js?

Sie möchten das Frontend mit React oder Vue bauen – aber das separate Entwerfen, Implementieren und Verwalten einer API vermeiden? Dieses Dilemma löst **Inertia.js**.

Inertia ist ein „Kleber" (Glue), der Sie serverseitiges Routing und Controller unverändert lassen und nur das Frontend mit React, Vue oder Svelte schreiben lässt. Es ist kein Framework, sondern eine Adapterschicht, die das bestehende Laravel mit einem JavaScript-Framework verbindet.

<Info>
  Die aktuelle Version ist Inertia v3 (veröffentlicht am 26. März 2026). Die Starterkits von Laravel 13 (React, Vue, Svelte) sind bereits Inertia-fähig.
</Info>

### Unterschiede zu klassischen SPAs/MPAs

| Architektur                     | Merkmale                                    | Herausforderungen                                               |
| ------------------------------- | ------------------------------------------- | --------------------------------------------------------------- |
| MPA (klassische Blade-App)      | Einfach, leicht mit Laravel zu integrieren  | Vollständiges Reload bei jedem Seitenwechsel                    |
| SPA (API + separates Frontend)  | Hohe Interaktivität                         | Doppelte Verwaltung von API-Design, Authentifizierung und Typen |
| **Inertia (moderner Monolith)** | UX einer SPA bei serverseitiger Einfachheit | Eigene Lernkurve                                                |

Mit Inertia können Sie aus einem Laravel-Controller direkt Daten an eine Vue- oder React-Komponente übergeben. Eine REST-API muss nicht definiert werden, und Seitenwechsel erfolgen per XHR statt per vollständigem Browser-Reload – so entsteht das flüssige Bedienerlebnis einer SPA.

***

## Zusammenhang mit den Laravel-Starterkits

Wenn Sie bei `laravel new` React, Vue oder Svelte wählen, wird Inertia automatisch eingerichtet.

```shell theme={null}
laravel new my-app
# Wählen Sie im interaktiven Prompt React / Vue / Svelte, um eine Inertia-Konfiguration zu erhalten
```

In den Starterkits ist folgendes bereits vorkonfiguriert:

* `inertiajs/inertia-laravel` (serverseitiger Adapter)
* `@inertiajs/react` / `@inertiajs/vue3` / `@inertiajs/svelte` (Client-Adapter)
* Middleware `HandleInertiaRequests`
* Authentifizierungsseiten für Login, Registrierung, Passwort-Reset u. a. (bereits als Inertia-Komponenten implementiert)

Für die manuelle Integration in bestehende Projekte installieren Sie die serverseitigen und clientseitigen Pakete separat. Details finden Sie in der Installationsanleitung der offiziellen Dokumentation.

***

## Grundlagen von `Inertia::render()`

Um aus einem Laravel-Controller eine Inertia-Response zurückzugeben, verwenden Sie `Inertia::render()`. Der erste Parameter ist der Name der JavaScript-Komponente, der zweite die als Props zu übergebenden Daten.

```php theme={null}
use Inertia\Inertia;

class PostController extends Controller
{
    public function index()
    {
        return Inertia::render('Posts/Index', [
            'posts' => Post::latest()->paginate(10),
        ]);
    }

    public function show(Post $post)
    {
        return Inertia::render('Posts/Show', [
            'post' => $post->only('id', 'title', 'content', 'created_at'),
            'author' => $post->user->only('id', 'name'),
        ]);
    }
}
```

<Tip>
  Statt `Inertia::render()` können Sie auch die Helper-Funktion `inertia()` verwenden. Legen Sie im Team einheitlich fest, welche der beiden verwendet wird.
</Tip>

Der Komponentenname `'Posts/Index'` entspricht dem Dateipfad. Bei React ist das `resources/js/Pages/Posts/Index.jsx`, bei Vue `resources/js/Pages/Posts/Index.vue`.

***

## Struktur einer Page-Komponente

Inertia-Page-Komponenten sind gewöhnliche Vue-/React-Komponenten. Die aus dem Controller übergebenen Daten werden als Props empfangen.

```jsx React theme={null}
// resources/js/Pages/Posts/Index.jsx
import { Link } from '@inertiajs/react'

export default function PostsIndex({ posts }) {
    return (
        <div>
            <h1>Beitragsübersicht</h1>
            {posts.data.map(post => (
                <article key={post.id}>
                    <h2>
                        <Link href={`/posts/${post.id}`}>{post.title}</Link>
                    </h2>
                </article>
            ))}
        </div>
    )
}
```

```vue Vue theme={null}
<!-- resources/js/Pages/Posts/Index.vue -->
<script setup>
import { Link } from '@inertiajs/vue3'

defineProps({
    posts: Object,
})
</script>

<template>
    <div>
        <h1>Beitragsübersicht</h1>
        <article v-for="post in posts.data" :key="post.id">
            <h2>
                <Link :href="`/posts/${post.id}`">{{ post.title }}</Link>
            </h2>
        </article>
    </div>
</template>
```

Mit der `<Link>`-Komponente erfolgen Seitenwechsel per XHR, ein vollständiges Seiten-Reload wird vermieden. Sie schreibt sich genau wie ein normaler `<a>`-Tag, im Hintergrund tauscht Inertia jedoch nur die Page-Komponente aus.

***

## Shared Data – die `HandleInertiaRequests`-Middleware

Daten, die auf allen Seiten gemeinsam benötigt werden (angemeldeter Benutzer, Flash-Messages usw.), definieren Sie in der Methode `share()` der Middleware `HandleInertiaRequests`.

```php theme={null}
// app/Http/Middleware/HandleInertiaRequests.php
use Illuminate\Http\Request;
use Inertia\Middleware;

class HandleInertiaRequests extends Middleware
{
    public function share(Request $request): array
    {
        return array_merge(parent::share($request), [
            'appName' => config('app.name'),

            'auth' => [
                'user' => $request->user()
                    ? $request->user()->only('id', 'name', 'email')
                    : null,
            ],

            'flash' => [
                'success' => $request->session()->get('success'),
                'error' => $request->session()->get('error'),
            ],
        ]);
    }
}
```

Shared Data werden automatisch in die Props jeder Seite gemergt.

```jsx React theme={null}
// Beispiel: Zugriff aus einer Layout-Komponente
import { usePage } from '@inertiajs/react'

export default function Layout({ children }) {
    const { auth, flash } = usePage().props

    return (
        <main>
            <header>
                {auth.user ? `Angemeldet: ${auth.user.name}` : 'Gast'}
            </header>
            {flash.success && <div className="alert-success">{flash.success}</div>}
            <article>{children}</article>
        </main>
    )
}
```

<Info>
  Da Shared Data in jeder Anfrage enthalten sind, empfiehlt es sich, sie auf das Nötigste zu beschränken. Mit einer Lazy-Evaluation per `fn()` werden sie nur dann ausgewertet, wenn sie in der jeweiligen Anfrage tatsächlich benötigt werden.
</Info>

***

## Formularübermittlung und Umgang mit Validierungsfehlern

Die Formularverarbeitung in Inertia integriert sich nahtlos in Laravels Validierung. Mit dem Helper `useForm()` lassen sich State-Handling, Absenden und Fehlerdarstellung schlank umsetzen.

### Auf der Controller-Seite

```php theme={null}
class PostController extends Controller
{
    public function store(Request $request)
    {
        $validated = $request->validate([
            'title'   => ['required', 'string', 'max:255'],
            'content' => ['required', 'string'],
        ]);

        Post::create($validated + ['user_id' => auth()->id()]);

        return redirect()->route('posts.index')
            ->with('success', 'Der Beitrag wurde erstellt.');
    }
}
```

Bei Validierungsfehlern leitet Laravel automatisch zurück zur Formularseite und speichert die Fehlerinformationen in der Session. Inertia erkennt dies automatisch und übergibt sie als `errors`-Prop an die Seite.

### Auf der Frontend-Seite

```jsx React theme={null}
// resources/js/Pages/Posts/Create.jsx
import { useForm } from '@inertiajs/react'

export default function PostsCreate() {
    const { data, setData, post, processing, errors } = useForm({
        title: '',
        content: '',
    })

    function handleSubmit(e) {
        e.preventDefault()
        post('/posts')
    }

    return (
        <form onSubmit={handleSubmit}>
            <div>
                <label>Titel</label>
                <input
                    value={data.title}
                    onChange={e => setData('title', e.target.value)}
                />
                {errors.title && <p className="error">{errors.title}</p>}
            </div>

            <div>
                <label>Inhalt</label>
                <textarea
                    value={data.content}
                    onChange={e => setData('content', e.target.value)}
                />
                {errors.content && <p className="error">{errors.content}</p>}
            </div>

            <button type="submit" disabled={processing}>
                {processing ? 'Wird gesendet...' : 'Veröffentlichen'}
            </button>
        </form>
    )
}
```

```vue Vue theme={null}
<!-- resources/js/Pages/Posts/Create.vue -->
<script setup>
import { useForm } from '@inertiajs/vue3'

const form = useForm({
    title: '',
    content: '',
})

function submit() {
    form.post('/posts')
}
</script>

<template>
    <form @submit.prevent="submit">
        <div>
            <label>Titel</label>
            <input v-model="form.title" />
            <p v-if="form.errors.title" class="error">{{ form.errors.title }}</p>
        </div>

        <div>
            <label>Inhalt</label>
            <textarea v-model="form.content"></textarea>
            <p v-if="form.errors.content" class="error">{{ form.errors.content }}</p>
        </div>

        <button type="submit" :disabled="form.processing">
            {{ form.processing ? 'Wird gesendet...' : 'Veröffentlichen' }}
        </button>
    </form>
</template>
```

Wenn Validierungsfehler zurückkommen, behält `useForm()` die Eingaben und stellt die Fehler dar. Die Benutzer müssen keine Formulare erneut ausfüllen, was das Nutzererlebnis verbessert.

***

## Passende und weniger passende Anwendungsfälle

### Wann Inertia gut geeignet ist

* Wenn ein mit Laravel vertrautes Team eine SPA-artige UI bauen möchte
* Wenn Authentifizierung, Autorisierung und Validierung zentral auf der Laravel-Seite bleiben sollen
* Für Admin-Panels, interne Tools und andere Anwendungen mit geringer SEO-Priorität
* Für Projekte, die die Kosten für ein separates API-Design und dessen Verwaltung vermeiden wollen

### Wann Inertia weniger geeignet ist

* Wenn mehrere externe Clients (z. B. Mobile Apps) dieselbe API verwenden
* Für Content-Sites mit hoher SEO-Priorität (per SSR möglich, wird aber komplex)
* Für Microfrontend-Konstellationen, in denen das Frontend von einem vollständig separaten Team entwickelt wird

<Tip>
  Inertia unterstützt auch Server-Side Rendering (SSR). Wenn Sie Seiten mit SEO-Bedarf haben, sollten Sie die SSR-Option in Betracht ziehen. Auch die Laravel-Starterkits enthalten bereits eine SSR-Konfiguration.
</Tip>

***

## Wichtigste Änderungen in Inertia v3

Inertia v3 wurde am 26. März 2026 veröffentlicht. Hier die wichtigsten Änderungen gegenüber v2.

### Axios wurde entfernt – hin zu einem leichtgewichtigen eingebauten XHR-Client

In v3 wurde Axios entfernt und durch einen leichteren, eingebauten XHR-Client ersetzt. Die meisten Anwendungen benötigen keine Codeänderungen. Axios-Interceptors lassen sich direkt auf die eingebauten Interceptors migrieren. Wer weiter Axios verwenden möchte, kann dies über den Axios-Adapter tun.

### Vereinfachtes SSR dank Plugin `@inertiajs/vite`

Das neue Vite-Plugin vereinfacht die automatische Auflösung von Page-Komponenten und die SSR-Konfiguration erheblich. SSR läuft während der Entwicklung allein durch `npm run dev`; ein separater Node-Server ist nicht mehr nötig.

```bash theme={null}
npm install @inertiajs/vite@^3.0
```

### Hook `useHttp` – HTTP-Requests ohne Seitenwechsel

Mit dem Hook `useHttp` senden Sie HTTP-Requests an den Server, ohne einen Seitenwechsel (Inertia visit) auszulösen. Hilfreich beim Speichern in Modalen, bei Hintergrundoperationen und weiteren Szenarien, in denen die aktuelle Seite erhalten bleiben soll.

### Optimistische UI-Updates (Optimistic Updates)

Sowohl `useForm` als auch die Router-Ebene unterstützen optimistische Updates. Die UI wird sofort aktualisiert, ohne die Server-Antwort abzuwarten; bei Fehlschlag erfolgt automatisch ein Rollback.

### Layout-Props

Mit dem Hook `useLayoutProps` lassen sich Daten aus einer Page-Komponente an ein persistentes Layout übergeben. Der zuvor auf Shared Data oder Page-Props beschränkte Anwendungsfall „Layout-Zustandssteuerung für bestimmte Seiten" wird deutlich einfacher.

### Änderungen bei den Voraussetzungen

In v3 wurden die minimalen Versionen angehoben.

| Position | v2   | v3   |
| -------- | ---- | ---- |
| PHP      | 8.1+ | 8.2+ |
| Laravel  | 10+  | 11+  |
| React    | 18+  | 19+  |
| Svelte   | 4+   | 5+   |

### Entfernung von `Inertia::lazy()`

Das in v2 als deprecated markierte `Inertia::lazy()` wurde in v3 vollständig entfernt. Verwenden Sie stattdessen `Inertia::optional()`.

```php theme={null}
// v2 (deprecated)
'users' => Inertia::lazy(fn () => User::all()),

// v3
'users' => Inertia::optional(fn () => User::all()),
```

### Umbenennung von Events

| v2          | v3              |
| ----------- | --------------- |
| `invalid`   | `httpException` |
| `exception` | `networkError`  |

### Entfernung der Option `future`

Der in v2 als experimenteller Konfigurationsblock verfügbare `future`-Block wurde entfernt. Alle dortigen Optionen sind nun standardmäßig aktiv. Entfernen Sie den `future`-Block aus der Konfiguration von `createInertiaApp`.

<Info>
  Details zum Upgrade von v2 finden Sie im <a href="https://inertiajs.com/docs/v3/getting-started/upgrade-guide">offiziellen Upgrade-Guide</a>. v2 erhält Bugfixes bis 26. September 2026 und Security-Fixes bis 26. März 2027.
</Info>

***

## Fazit

Inertia.js beantwortet den realen Bedarf „Laravel unverändert lassen, aber das Frontend in React/Vue schreiben". Die Möglichkeit, Daten direkt aus einem Controller an eine Komponente zu übergeben, ohne eine API entwerfen zu müssen, ist die größte Stärke.

Dass die Starterkits von Laravel 13 Inertia unterstützen, unterstreicht seine gefestigte Position im Laravel-Ökosystem. Wenn Livewire der Ansatz ist, dynamische UIs allein mit PHP zu erstellen, ist Inertia der Ansatz, die Stärke von JavaScript-Frameworks zu nutzen, ohne die serverseitige Einfachheit zu verlieren.

Welche Option Sie wählen, hängt von den Fähigkeiten Ihres Teams und den Projektanforderungen ab. Für das Szenario „Laravel-Controller unverändert lassen und Screens mit React bauen" ist Inertia jedoch die natürlichste Wahl.

<Card title="Offizielle Dokumentation von Inertia.js" icon="book-open" href="https://inertiajs.com">
  Alle Funktionen von Inertia v3 finden Sie in der offiziellen Dokumentation.
</Card>


## Related topics

- [Vue.js – Einstieg mit Inertia × Laravel](/de/blog/vue-introduction.md)
- [Starter Kits](/de/starter-kits.md)
- [Asset-Bundling mit Vite](/de/vite.md)
- [Frontend](/de/frontend.md)
- [React – Einstieg mit Inertia × Laravel](/de/blog/react-introduction.md)
