Usprawnienia i optymalizacja w Livewire

Optymalizacja jest kluczowa przy budowaniu aplikacji, szczególnie kiedy liczba użytkowników rośnie i rosną także wymagania dotyczące wydajności. W kontekście Livewire możemy wprowadzić różne usprawnienia, które pozwalają zredukować liczbę żądań AJAX, odciążyć bazę danych lub przyspieszyć działanie interfejsu. W dzisiejszym artykule przyjrzymy się, jak zastosować takie techniki, od usprawnienia komunikacji pomiędzy front-endem i backendem, przez caching, aż po metody debugowania.

Artykuł jest kontynuacją naszych wcześniejszych materiałów:

Optymalizacja liczby wywołań AJAX

Livewire komunikuje się z backendem poprzez serię żądań AJAX, automatycznie wykonywanych przy zmianach stanu komponentu. Jeśli jednak mamy wiele pól powiązanych z wire:model, może to generować zbyt wiele zapytań. Poniżej prezentujemy trzy modyfikatory, które pomogą zmniejszyć tę liczbę:

wire:model.lazy

Zamiast reagować na każdą zmianę w polu (każde wpisywanie znaku), wire:model.lazy wysyła żądanie dopiero po „wyjściu” z pola (np. po zmianie fokusu). Oznacza to, że jeśli użytkownik wypełnia pole tekstowe, Livewire poczeka, aż zakończy on edycję, zanim odświeży stan komponentu.

				
					<input type="text" wire:model.lazy="searchQuery" placeholder="Szukaj...">

				
			

wire:model.defer

wire:model.defer zbiera zmiany w polu i wysyła je dopiero, gdy użytkownik wykona jakąś akcję, która wymusza synchronizację z backendem – na przykład, gdy kliknie przycisk z wire:click lub zatwierdzi formularz z wire:submit.

				
					<input type="text" wire:model.defer="searchQuery" placeholder="Szukaj...">
<button wire:click="searchTasks">Szukaj</button>

				
			

W powyższym przykładzie zmiany w polu tekstowym nie będą wysyłane natychmiast, lecz dopiero po kliknięciu przycisku „Szukaj”.

wire:model.debounce

Debounce w Livewire pozwala wprowadzić opóźnienie przed wysłaniem żądania AJAX. Przykładowo, wire:model.debounce.500ms zbiera wpisywane znaki i wyśle aktualizację dopiero, gdy użytkownik przestanie pisać przez minimum 500 ms.

				
					<input type="text" wire:model.debounce.500ms="searchQuery" placeholder="Szukaj...">

				
			

Ta opcja jest bardzo przydatna przy tworzeniu pól wyszukiwania w locie, by nie przeciążać bazy danych ciągłymi żądaniami podczas wpisywania.

Zmniejszanie liczby odświeżeń akcji (np. wire:click.prevent)

Często zdarza się, że niektóre akcje w Livewire mogą powodować odświeżanie lub zachowania typowe dla elementów HTML. Dla przykładu, jeśli mamy przycisk w formularzu, standardowo kliknięcie może wysłać żądanie HTTP, co w kontekście Livewire może być niepożądane. W takich sytuacjach warto użyć modyfikatora .prevent:

				
					<button wire:click.prevent="saveTask">Zapisz zadanie</button>

				
			

Dzięki temu unikniemy domyślnej akcji kliknięcia (odświeżania strony), zachowując tylko wywołanie metody saveTask.

Integracja cachingu w Livewire

Wydajność bazy danych jest kluczowa w większości aplikacji. Jednym ze sposobów na odciążenie serwera jest cache’owanie wyników zapytań. W Laravelu możemy wykorzystać do tego Cache facade lub cache() helper.

W komponentach Livewire stosujemy podejście analogiczne do reszty Laravelowej aplikacji. Przykład poniżej pokazuje cache’owanie wyników skomplikowanego zapytania na 60 sekund:

				
					use Illuminate\Support\Facades\Cache;

// ...
public function getTasks()
{
    return Cache::remember('tasks_list', 60, function () {
        // Tu może być bardziej złożone zapytanie
        return Task::orderBy('created_at', 'desc')->get();
    });
}

				
			

Jeśli często wykonujemy to samo zapytanie, a dane nie zmieniają się co sekundę, taki mechanizm pozwala znacząco przyspieszyć działanie aplikacji.

Uwaga: Pamiętaj, żeby w razie aktualizacji bazy (np. dodania nowego zadania) wyczyścić lub odświeżyć cache, np. poprzez Cache::forget('tasks_list').

Debugowanie w Livewire

Livewire Devtools

Livewire Devtools to rozszerzenie do przeglądarek (obecnie działa w Chrome, Brave, Firefox), które pozwala podejrzeć stan komponentów, listę zarejestrowanych eventów, a nawet modelowane właściwości w czasie rzeczywistym. Aby z niego skorzystać, należy:

  1. Zainstalować rozszerzenie Livewire Devtools w przeglądarce.
  2. Upewnić się, że w aplikacji jest zainstalowany pakiet livewire/livewire.
  3. Otworzyć narzędzia deweloperskie w przeglądarce i przejść do zakładki „Livewire”.

Debugbar i inne narzędzia

Aby debugować zapytania do bazy danych, można posłużyć się np. pakietem Laravel Debugbar. Pozwala on podejrzeć wszystkie wykonywane zapytania, co jest szczególnie ważne, kiedy chcemy zidentyfikować obszary, w których aplikacja może być przeciążona.
Inną metodą jest oczywiście klasyczne logowanie (\Log::info($dane)) wewnątrz metod Livewire i przeglądanie logów w pliku storage/logs/laravel.log.

Ćwiczenia

Poniżej przedstawiam dwa proste ćwiczenia, które pomogą Ci w praktyczny sposób opanować omówione zagadnienia.

Ćwiczenie 1. Dodanie wyszukiwania z mechanizmem debounce

Załóżmy, że w naszej aplikacji mamy komponent TaskList, który wyświetla listę zadań. W tym ćwiczeniu dodamy pole wyszukiwania, tak aby użytkownik mógł filtrować zadania po nazwie.

Krok 1: Dodaj właściwość w komponencie

				
					public $searchQuery = '';

				
			

Krok 2: Zastosuj wire:model.debounce

W widoku Blade, gdzie chcemy umożliwić wyszukiwanie:

				
					<input type="text" wire:model.debounce.500ms="searchQuery" placeholder="Szukaj zadań...">

<ul>
    @foreach($tasks as $task)
        <li>{{ $task->name }}</li>
    @endforeach
</ul>

				
			

Krok 3: Modyfikacja metody pobierającej zadania

				
					public function getTasksQuery()
{
    // Jeśli użytkownik wpisał coś do wyszukiwania – filtrujemy
    $query = Task::query();

    if (!empty($this->searchQuery)) {
        $query->where('name', 'LIKE', '%' . $this->searchQuery . '%');
    }

    return $query->orderBy('created_at', 'desc');
}

public function render()
{
    // Tutaj używamy metody getTasksQuery()
    $tasks = $this->getTasksQuery()->paginate(10);

    return view('livewire.task-list', compact('tasks'));
}

				
			

Dzięki debounce, żądanie do Livewire pójdzie dopiero po 500 ms nieaktywności użytkownika podczas wpisywania. W efekcie nie będziemy „spamować” serwera zapytaniami co ułamek sekundy.

Ćwiczenie 2: Cache zapytania

Załóżmy, że nasza lista zadań pobiera dane z bazy, a chcemy ograniczyć liczbę zapytań. Możemy cache’ować wyniki na pewien czas (np. 60 sekund).

Krok 1: Dodaj logikę cache w metodzie pobierającej zadania

				
					use Illuminate\Support\Facades\Cache;

public function getTasksQuery()
{
    return Cache::remember('tasks.list.' . $this->searchQuery, 60, function () {
        $query = Task::query();

        if (!empty($this->searchQuery)) {
            $query->where('name', 'LIKE', '%' . $this->searchQuery . '%');
        }

        return $query->orderBy('created_at', 'desc');
    });
}

				
			

Tutaj klucz cache uwzględnia zmienną searchQuery – jeśli się różni, to cache będzie inny (zapewnia to osobny wynik dla różnych filtrów wyszukiwania).

Krok 2: Odświeżanie cache przy zmianach w bazie

Kiedy dodajemy nowe zadanie, powinniśmy odświeżyć cache. Możemy to zrobić w komponencie odpowiedzialnym za dodawanie lub edycję zadań:

				
					public function createTask()
{
    $this->validate();

    Task::create([
        'name'   => $this->name,
        'status' => $this->status,
    ]);

    // Czyszczenie cache przy dodaniu nowego zadania
    Cache::forget('tasks.list.' . $this->searchQuery);

    $this->emit('zadanieUtworzone');
}

				
			

Dodatkowo, jeśli mamy wiele wariantów kluczy (np. różne searchQuery), możemy rozważyć zapisywanie danych w osobnym kluczu (np. Cache::forget('tasks.list.*') z użyciem wildcard) bądź w bazie innego mechanizmu do szerszego czyszczenia cache.

Podsumowanie

Livewire domyślnie zapewnia wysoki komfort pracy, jednak w przypadku bardziej złożonych aplikacji warto wprowadzać dodatkowe optymalizacje:

  1. Zmniejszenie liczby wywołań AJAX – użycie modyfikatorów lazy, defer, debounce, a także świadome posługiwanie się wire:click.prevent.
  2. Caching – w prosty sposób integrujemy się z Laravel Cache, co pozwala odciążyć bazę danych.
  3. Debugowanie – korzystanie z Livewire Devtools i Laravel Debugbar, które pomagają nam w wyłapaniu wąskich gardeł i błędów.

Dzięki tym praktykom Twoja aplikacja napisania w Laravel + Livewire może być jeszcze bardziej responsywna, niezawodna i skalowalna. To znacznie poprawi doświadczenie użytkowników końcowych i ułatwi dalszy rozwój projektu.