Livewire vs. Inertia.js vs. klasické SPA — kedy čo?
Pred tým, než začneme s kódom, treba pochopiť, kde Livewire dáva zmysel a kde nie. Toto rozhodnutie ovplyvní celú architektúru projektu.
| Kritérium | Livewire 3 | Inertia.js + Vue/React | SPA (API + frontend) |
|---|---|---|---|
| Tím | PHP vývojári | PHP + JS vývojári | Separátne tímy |
| Rýchlosť vývoja | Vysoká | Stredná | Nízka |
| SEO | Výborne (SSR) | Dobre (SSR možné) | Komplikované |
| Real-time (WebSocket) | Cez Reverb/Echo | Cez Echo | Natívne |
| Offline podpora | Nie | Obmedzene | Áno (PWA) |
| Veľké SPA aplikácie | Nevhodné | Vhodné | Ideálne |
Livewire 3 je ideálny pre: CRUD administrácie, rezervačné systémy, dashboardy, formuláre s komplexnou validáciou, live vyhľadávanie a filtrovanie — všetko v rámci monolitickej Laravel aplikácie.
Inštalácia Livewire 3
Livewire 3 vyžaduje Laravel 10+ a PHP 8.1+. Inštalácia cez Composer pridá Blade direktívy a automaticky zaregistruje middleware.
composer require livewire/livewire
# Voliteľné: publikovať konfiguráciu
php artisan livewire:publish --config
Do hlavného Blade layoutu pridajte Livewire skripts a štýly — Livewire 3 ich vkladá automaticky cez @livewireScripts a @livewireStyles, alebo môžete použiť nový @livewire tag:
<!-- resources/views/layouts/app.blade.php -->
<html>
<head>
@livewireStyles
</head>
<body>
{{ $slot }}
@livewireScripts
</body>
</html>
Prvý komponent — živé vyhľadávanie
Komponent pozostáva z dvoch súborov: PHP triedy a Blade šablóny. Vytvoríme ich jedným príkazom:
php artisan make:livewire ProductSearch
Toto vytvorí app/Livewire/ProductSearch.php a resources/views/livewire/product-search.blade.php.
<?php
// app/Livewire/ProductSearch.php
namespace App\Livewire;
use Livewire\Component;
use Livewire\WithPagination;
use App\Models\Product;
class ProductSearch extends Component
{
use WithPagination;
public string $search = '';
public string $category = 'all';
// Každá zmena $search automaticky resetuje stránkovanie
public function updatingSearch(): void
{
$this->resetPage();
}
public function render()
{
return view('livewire.product-search', [
'products' => Product::query()
->when($this->search, fn($q) => $q->where('name', 'like', "%{$this->search}%"))
->when($this->category !== 'all', fn($q) => $q->where('category', $this->category))
->paginate(12),
]);
}
}
<!-- resources/views/livewire/product-search.blade.php -->
<div>
<input
wire:model.live.debounce.300ms="search"
type="search"
placeholder="Hľadať produkt..."
class="w-full px-4 py-2 rounded-lg bg-gray-800 border border-gray-700"
>
<div class="grid grid-cols-3 gap-4 mt-6">
@foreach($products as $product)
<div wire:key="{{ $product->id }}" class="card">
<h3>{{ $product->name }}</h3>
<p>{{ $product->price }} EUR</p>
</div>
@endforeach
</div>
{{ $products->links() }}
</div>
.live posiela AJAX request pri každom stlačení klávesy (s debounce), .blur až po opustení poľa. Pre vyhľadávanie použite .live.debounce.300ms, pre formulárové polia .blur.
Properties, Actions a Lifecycle hooks
Livewire komponent je PHP trieda so verejnými properties (automaticky synchrónizované s frontendom) a metódami (volateľné cez wire:click).
class ShoppingCart extends Component
{
public array $items = [];
public float $discount = 0;
// Lifecycle hook — volá sa pred každým hydrate
public function boot(): void
{
// Inicializácia závislostí
}
// Action — volá sa cez wire:click="addItem(productId)"
public function addItem(int $productId): void
{
$product = Product::findOrFail($productId);
$this->items[] = ['id' => $product->id, 'name' => $product->name, 'price' => $product->price];
// Dispatch browser event pre Alpine.js / JavaScript
$this->dispatch('cart-updated', count: count($this->items));
}
// Computed property (Livewire 3) — cachovaná v rámci jedného requestu
#[\Livewire\Attributes\Computed]
public function total(): float
{
return collect($this->items)->sum('price') * (1 - $this->discount / 100);
}
}
Formuláre a validácia
Livewire 3 prináša dedikovanú Form Object triedu — ideálne pre zložité formuláre s validáciou a resetovaním stavu.
<?php
// app/Livewire/Forms/ContactForm.php
namespace App\Livewire\Forms;
use Livewire\Form;
class ContactForm extends Form
{
public string $name = '';
public string $email = '';
public string $message = '';
protected function rules(): array
{
return [
'name' => 'required|min:2|max:100',
'email' => 'required|email',
'message' => 'required|min:20|max:2000',
];
}
public function submit(): void
{
$this->validate();
// Odoslanie e-mailu, uloženie do DB...
$this->reset();
}
}
// app/Livewire/ContactPage.php
class ContactPage extends Component
{
public ContactForm $form;
public bool $submitted = false;
public function submit(): void
{
$this->form->submit();
$this->submitted = true;
}
}
<!-- Blade template -->
<form wire:submit="submit">
<input wire:model.blur="form.email" type="email">
@error('form.email') <span class="text-red-400">{{ $message }}</span> @enderror
<button type="submit" wire:loading.attr="disabled">
<span wire:loading.remove>Odoslať</span>
<span wire:loading>Odosielam...</span>
</button>
</form>
@if($submitted)
<div class="bg-green-500/20 text-green-400 p-4 rounded-lg">Správa odoslaná!</div>
@endif
Real-time s Laravel Reverb a Echo
Pre skutočný real-time (WebSocket, nie polling) Livewire 3 spolupracuje s Laravel Reverb — novým first-party WebSocket serverom od Laravel 11+.
# Inštalácia Reverb
composer require laravel/reverb
php artisan reverb:install
# Spustenie WebSocket servera
php artisan reverb:start
// Emitovanie eventu z backend kódu (napr. Job)
use App\Events\OrderStatusUpdated;
broadcast(new OrderStatusUpdated($order));
// V Livewire komponente — počúvanie na broadcast event
class OrderTracker extends Component
{
public Order $order;
#[\Livewire\Attributes\On('echo:orders.{order.id},OrderStatusUpdated')]
public function refreshOrder(): void
{
$this->order->refresh();
}
}
wire:poll.5s atribút priamo v Blade šablóne. Pre dashboardy s aktualizáciou každých niekoľko sekúnd je to dostačujúce riešenie.
Alpine.js + Livewire — perfektná kombinácia
Livewire 3 je dodávaný s Alpine.js zabudovaným — nie je potrebná samostatná inštalácia. Alpine rieši lokálny UI stav (modálne okná, dropdown, animácie), Livewire rieši serverový stav (databáza, validácia, autentifikácia).
<!-- Modálne okno riadené Alpine.js, obsah načítaný cez Livewire -->
<div x-data="{ open: false }">
<button @click="open = true">Detail produktu</button>
<div x-show="open" @keydown.escape.window="open = false">
<!-- Livewire komponent sa inicializuje keď je open=true -->
@if($open)
<livewire:product-detail :productId="$product->id" />
@endif
<button @click="open = false">Zavrieť</button>
</div>
</div>
<!-- Komunikácia Livewire → Alpine cez $dispatch -->
<!-- V Livewire PHP: $this->dispatch('show-toast', message: 'Uložené!') -->
<div x-data="{ message: '' }" @show-toast.window="message = $event.detail.message">
<div x-show="message" x-text="message"></div>
</div>
Lazy loading komponentov
Livewire 3 podporuje lazy loading — komponent sa načíta až po prvom renderi stránky. Ideálne pre drahé databázové operácie, ktoré nie sú kritické pre prvé zobrazenie.
<!-- Lazy loading s placeholder -->
<livewire:sales-chart lazy>
<!-- Placeholder kým sa komponent nenačíta -->
<div class="animate-pulse bg-gray-800 h-64 rounded-xl"></div>
</livewire:sales-chart>
// V PHP triede označte metódu pre placeholder
class SalesChart extends Component
{
public function placeholder()
{
return view('livewire.placeholders.chart-skeleton');
}
public function render()
{
// Táto metóda sa zavolá až po lazy načítaní
return view('livewire.sales-chart', [
'data' => $this->calculateExpensiveChartData(),
]);
}
}
Testovanie Livewire komponentov
Livewire 3 prináša Livewire::test() helper, ktorý simuluje celý životný cyklus komponentu vrátane AJAX requestov — bez potreby skutočného prehliadača.
use Livewire\Livewire;
use App\Livewire\ProductSearch;
it('filtruje produkty podľa vyhľadávania', function () {
Product::factory()->create(['name' => 'Laravel kurz']);
Product::factory()->create(['name' => 'PHP kniha']);
Livewire::test(ProductSearch::class)
->set('search', 'Laravel')
->assertSee('Laravel kurz')
->assertDontSee('PHP kniha');
});
it('volá submit akciu a validuje formulár', function () {
Livewire::test(ContactPage::class)
->set('form.email', 'neplatny-email')
->call('submit')
->assertHasErrors(['form.email' => 'email'])
->assertNotDispatched('contact-submitted');
});
Performance: wire:key a dôležité optimalizácie
Niekoľko pravidiel, ktoré zabránia zbytočným re-renderom a pomalým AJAX requestom:
- Vždy používajte
wire:keyv slučkách — Livewire vie priradiť DOM elementy k PHP objektom a nevytvárať ich znovu #[Computed]atribút pre drahé výpočty — výsledok je kešovaný počas celého HTTP requestu- Vyhnite sa veľkým public properties — Livewire serializuje všetky public properties do každého AJAX requestu. Namiesto celého Eloquent modelu prenášajte len ID
wire:model.blurnamiesto.livepre bežné formulárové polia — redukuje počet AJAX requestov- Lazy loading pre komponenty pod the fold — znižuje Time to Interactive hlavnej stránky
render() sa volá pri každom AJAX requeste komponentu. Používajte with(['products' => ...]) so správnymi eager loads a kešovaním, aby každý klik nezahlcoval databázu.
Záver: Livewire 3 ako default voľba pre Laravel projekty
Livewire 3 výrazne znížil overhead fullstack vývoja pre PHP tímy. Ak vaša aplikácia nevyžaduje offline podporu, komplexný real-time (napr. multiplayer) alebo separátny mobilný klient, Livewire 3 vám ušetrí dni vývoja oproti Inertia.js + React.
Kombinovaný s Alpine.js pre lokálny UI stav a Laravel Reverb pre WebSocket pokryje 90 % prípadov použitia modernej webovej aplikácie — a ostanete v PHP ekosystéme, ktorý poznáte.
Potrebujete Laravel alebo Livewire vývoj?
Postavím vám reaktívnu Laravel aplikáciu s Livewire 3 — od architektúry komponentov po nasadenie. Cenová ponuka do 24 hodín.
Nezáväzný dopyt