Livewire 4 erschien im Januar 2026 mit einem verfeinerten Komponentenlebenszyklus, standardmäßigem Lazy Loading und nativen Form-Objekten. Wer in den letzten Jahren zwischen Vue, React und Inertia hin- und hergesprungen ist, nur um reaktive Oberflächen in eine Laravel-Anwendung zu bringen, bekommt mit diesem Release eine ernsthafte Einladung, zurückzukehren. Dieser Leitfaden zeigt, worauf es wirklich ankommt, wenn Sie Livewire 4 in Produktion nehmen: kein Hello-World-Zähler, sondern die Muster, die echten Traffic überstehen.
Was Sie am Ende dieses Leitfadens ausgeliefert haben
- Eine Livewire-4-Komponente mit Form-Objekten, Validierung und Lazy Loading
- Alpine-Interop für clientseitigen Feinschliff, ohne das servergesteuerte Modell zu verlassen
- Einen Datei-Upload-Ablauf mit Fortschrittsanzeige, Validierung und S3-Speicherung
- Pest-Tests, die die Komponente durchgängig prüfen
- Produktions-Checkliste: Caching, Asset-Versionierung und die Fallstricke, die unter Last zubeißen
Info
Für wen ist das gedacht
Sie sind mit Laravel-Routen, Controllern und Eloquent vertraut. Vielleicht haben Sie schon Livewire 2 oder 3 genutzt. Wir halten uns nicht mit Erklärungen zu Artisan oder Composer auf.
Warum Livewire 4 die Rechnung verändert
Livewire 3 war die Neuimplementierung, die das Framework wirklich schnell machte. Livewire 4 ist der Feinschliff: Lazy Components sind jetzt der Standard für geroutete Einstiegspunkte, Form-Objekte haben ad-hoc-öffentliche Eigenschaften als kanonisches Muster abgelöst, und das neue Islands Primitiv erlaubt es, Teile einer Seite in unabhängige Neu-Renderings auszulagern. Das Ergebnis sind weniger Payloads, kleinere Diffs und weit weniger von dem Schmerz, dass bei jedem Tastendruck alles neu rendert, der Livewire 2 plagte.
✓ Vorteile
- Keine API oder JSON-Verträge zu pflegen: der Wire ist unsichtbar
- Serverseitige Validierung ist die Validierung; keine Duplizierung
- Autorisierung, Eager Loading und Eloquent funktionieren einfach
- Pest-Tests treiben Komponenten ohne Browser an
✕ Nachteile
- Latenzempfindliche UIs (Drag, Slider, Canvas) brauchen weiterhin Alpine oder eine echte SPA
- Jede Komponente überträgt bei jedem Roundtrip die vollständigen Props: halten Sie sie klein
- Langlaufende Aktionen sollten Jobs dispatchen, nicht den Request blockieren
1. Form-Objekte: das wichtigste Livewire-4-Muster
Hören Sie auf, Formularfelder direkt in Ihre Komponente zu packen. Ein Form-Objekt kapselt Zustand, Regeln und den Persistenzaufruf: die Komponente wird zur dünnen Hülle.
<?php
namespace App\Livewire\Forms;
use App\Models\Project;
use Livewire\Attributes\Validate;
use Livewire\Form;
class ProjectForm extends Form
{
public ?Project $project = null;
#[Validate('required|string|min:3|max:120')]
public string $name = '';
#[Validate('nullable|string|max:2000')]
public string $description = '';
#[Validate('required|in:draft,active,archived')]
public string $status = 'draft';
public function setProject(Project $project): void
{
$this->project = $project;
$this->name = $project->name;
$this->description = $project->description ?? '';
$this->status = $project->status;
}
public function save(): Project
{
$this->validate();
$project = $this->project
? tap($this->project)->update($this->only(['name', 'description', 'status']))
: Project::create($this->only(['name', 'description', 'status']));
$this->reset();
return $project;
}
}
Und die Komponente, die es nutzt:
<?php
namespace App\Livewire\Projects;
use App\Livewire\Forms\ProjectForm;
use App\Models\Project;
use Livewire\Attributes\Lazy;
use Livewire\Component;
#[Lazy]
class Edit extends Component
{
public ProjectForm $form;
public function mount(Project $project): void
{
$this->authorize('update', $project);
$this->form->setProject($project);
}
public function update(): void
{
$project = $this->form->save();
$this->dispatch('project-saved', id: $project->id);
session()->flash('status', 'Project updated.');
}
public function render(): \Illuminate\View\View
{
return view('livewire.projects.edit');
}
}
Profi-Tipp
Das Attribut #[Lazy] bewirkt, dass die Komponente beim ersten Rendern einen Platzhalter anzeigt und erst hydriert wird, nachdem die Seite interaktiv ist. Für Dashboards mit drei oder mehr Komponenten kann dieses einzelne Attribut die Time to Interactive um 30-50 % senken.
2. Alpine-Interop, ohne den Verstand zu verlieren
Livewire 4 wird mit einer engeren Alpine-Brücke ausgeliefert. Verwenden Sie wire:model.live.debounce.500ms für Eingaben, die den Server erreichen sollen, und Alpine für alles, was den Browser nie verlassen sollte: Öffnen/Schließen, Fokusfallen, Übergänge.
<div x-data="{ open: false }" class="rounded-xl border bg-white p-4">
<div class="flex items-center justify-between">
<h3 class="font-semibold">{{ $form->name ?: 'Untitled project' }}</h3>
<button type="button" @click="open = !open" class="text-sm text-teal-600">
<span x-text="open ? 'Hide details' : 'Show details'"></span>
</button>
</div>
<div x-show="open" x-collapse>
<input
type="text"
wire:model.live.debounce.500ms="form.name"
class="mt-3 w-full rounded-lg border-gray-300"
/>
@error('form.name') <p class="text-rose-600 text-sm">{{ $message }}</p> @enderror
</div>
<button wire:click="update" wire:loading.attr="disabled" class="mt-4 rounded-lg bg-teal-600 px-4 py-2 text-white">
<span wire:loading.remove>Save</span>
<span wire:loading>Saving…</span>
</button>
</div>
Warnung
Binden Sie Alpine-Zustand nicht an wire:model
Alpine und Livewire kämpfen um dasselbe DOM. Nutzen Sie Alpine für flüchtigen UI-Zustand (Modals, Akkordeons) und Livewire für persistierten Formularzustand. Die Ströme zu kreuzen erzeugt endlose Update-Schleifen.
3. Datei-Uploads mit Fortschritt und S3
Uploads sind der Hauptgrund, warum Teams zu SPA-Frameworks greifen. Livewire 4 handhabt sie sauber: temporärer lokaler Upload, Validierung, dann das Verschieben nach S3 dispatchen.
use Livewire\WithFileUploads;
use Livewire\Attributes\Validate;
class ProjectAttachments extends Component
{
use WithFileUploads;
public Project $project;
#[Validate(['files.*' => 'file|max:10240|mimes:pdf,png,jpg,docx'])]
public array $files = [];
public function save(): void
{
$this->validate();
foreach ($this->files as $file) {
$path = $file->storePubliclyAs(
"projects/{$this->project->id}",
Str::uuid().'.'.$file->getClientOriginalExtension(),
's3'
);
$this->project->attachments()->create([
'path' => $path,
'size' => $file->getSize(),
'mime' => $file->getMimeType(),
]);
}
$this->files = [];
$this->dispatch('attachments-saved');
}
}
Konfigurieren Sie das temporäre Laufwerk
Setzen Sie in config/livewire.php "temporary_file_upload.disk" auf "s3" und "directory" auf "livewire-tmp". Ohne dies landen große Uploads zuerst im lokalen Dateisystem und scheitern bei horizontalen Deployments.
Fügen Sie eine CORS-Regel für Ihren S3-Bucket hinzu
Erlauben Sie PUT und GET nur von Ihrer Anwendungsdomain. Livewire stellt eine vorab signierte URL für den Browser aus, daher muss der Bucket den Upload direkt akzeptieren.
Fügen Sie eine Lebenszyklusregel hinzu
Löschen Sie Objekte unter "livewire-tmp/" automatisch nach 24 Stunden. Andernfalls sammeln sich verwaiste Uploads für immer an.
4. Komponenten mit Pest testen
Die Livewire-Testhelfer fügen sich fließend in Pest ein. Kein Headless-Browser, keine wackeligen Wartezeiten.
use App\Livewire\Projects\Edit;
use App\Models\Project;
use App\Models\User;
it('updates a project owned by the user', function () {
$user = User::factory()->create();
$project = Project::factory()->for($user, 'owner')->create(['name' => 'Old']);
actingAs($user)
->livewire(Edit::class, ['project' => $project])
->set('form.name', 'Renamed Project')
->call('update')
->assertHasNoErrors()
->assertDispatched('project-saved');
expect($project->fresh()->name)->toBe('Renamed Project');
});
it('rejects updates from non-owners', function () {
$project = Project::factory()->create();
$intruder = User::factory()->create();
actingAs($intruder)
->livewire(Edit::class, ['project' => $project])
->assertForbidden();
});
5. Produktions-Checkliste
✓ Vorteile
- Führen Sie `php artisan livewire:publish --assets` aus und liefern Sie Assets über Ihr CDN aus
- Setzen Sie APP_URL korrekt: Livewire signiert URLs damit
- Cachen Sie Views und Routen (`view:cache`, `route:cache`)
- Richten Sie `wire:offline`-Behandlung für instabile Netzwerke ein
✕ Nachteile
- Aktivieren Sie `wire:poll` nicht auf mehr als einer Komponente pro Seite: es stapelt sich
- Vermeiden Sie es, große Eloquent-Modelle als Props zu übergeben: Livewire serialisiert sie bei jedem Request
- Öffentliche Eigenschaften einer Komponente werden an den Browser gesendet; weisen Sie niemals Geheimnisse zu
weniger ausgeliefertes JS im Vergleich zu einem äquivalenten Inertia + Vue Dashboard
Gefahr
Der häufigste Produktionsfehler
Zu vergessen, dass öffentliche Eigenschaften für den Client sichtbar sind. Wenn Sie <code>public User $user</code> setzen, wird das gesamte Modell hydriert und bei jedem Livewire-Request gesendet. Verwenden Sie <code>#[Locked]</code> für Eigenschaften, die der Client niemals ändern darf, und bevorzugen Sie IDs statt vollständiger Modelle, wann immer möglich.
Wo Livewire 4 passt und wo nicht
Livewire ist jetzt die richtige Standardlösung für Admin-Panels, Einstellungsseiten, Dashboards, mehrstufige Formulare und die meisten CRUD-Anwendungen. Es ist das falsche Werkzeug für kollaborative Editoren, Echtzeit-Canvas-Anwendungen oder alles, bei dem jeder Tastendruck eine Rückmeldung unter 50 ms erfordert. Setzen Sie in solchen Fällen auf Alpine für die Interaktionsebene und Livewire, um das Ergebnis zu persistieren.
Erfolg
In Produktion nehmen
Ein Livewire-4-Dashboard, bereitgestellt auf einer 20-Dollar-Forge-Box hinter Cloudflare, bedient problemlos tausende authentifizierte Benutzer. Greifen Sie nur dann zu SPAs, wenn die Produktanforderungen dies tatsächlich erfordern.
Kommentare
0Noch keine Kommentare. Teile als Erste oder Erster deine Gedanken.