Zum Hauptinhalt springen

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.
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.

Unterschiede zu klassischen SPAs/MPAs

ArchitekturMerkmaleHerausforderungen
MPA (klassische Blade-App)Einfach, leicht mit Laravel zu integrierenVollständiges Reload bei jedem Seitenwechsel
SPA (API + separates Frontend)Hohe InteraktivitätDoppelte Verwaltung von API-Design, Authentifizierung und Typen
Inertia (moderner Monolith)UX einer SPA bei serverseitiger EinfachheitEigene 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.
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.
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'),
        ]);
    }
}
Statt Inertia::render() können Sie auch die Helper-Funktion inertia() verwenden. Legen Sie im Team einheitlich fest, welche der beiden verwendet wird.
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.
React
// 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
<!-- 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.
// 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.
React
// 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>
    )
}
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.

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

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

React
// 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
<!-- 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
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.

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.
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.
Positionv2v3
PHP8.1+8.2+
Laravel10+11+
React18+19+
Svelte4+5+

Entfernung von Inertia::lazy()

Das in v2 als deprecated markierte Inertia::lazy() wurde in v3 vollständig entfernt. Verwenden Sie stattdessen Inertia::optional().
// v2 (deprecated)
'users' => Inertia::lazy(fn () => User::all()),

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

Umbenennung von Events

v2v3
invalidhttpException
exceptionnetworkError

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.
Details zum Upgrade von v2 finden Sie im offiziellen Upgrade-Guide. v2 erhält Bugfixes bis 26. September 2026 und Security-Fixes bis 26. März 2027.

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.

Offizielle Dokumentation von Inertia.js

Alle Funktionen von Inertia v3 finden Sie in der offiziellen Dokumentation.
Zuletzt geändert am 13. Juli 2026