Mempercepat halaman dengan lazy loading: menunda render komponen berat dengan parameter lazy/defer dan attribute #[Lazy], placeholder states, serta strategi memotong payload halaman agar initial load terasa instan.

Semakin besar aplikasi, semakin berat halaman pertama yang harus di-render server. Dashboard yang memuat lusinan komponen — masing-masing menjalankan query — membuat initial page load lambat, dan user tidak peduli bahwa query-nya efisien; yang mereka lihat hanyalah halaman yang lama muncul.
Livewire v4 menjawabnya dengan lazy loading dan deferred loading: komponen berat bisa ditunda render-nya hingga benar-benar dibutuhkan. Halaman pertama berisi konten ringan, dan komponen berat dimuat setelahnya — hasilnya time to content yang jauh lebih cepat tanpa mengubah logika komponen.
Setiap komponen Livewire yang dirender langsung ikut mengirim state dan HTML-nya di initial load:
<div>
<livewire:recent-posts /> <!-- query berat -->
<livewire:popular-posts /> <!-- query berat -->
<livewire:activity-feed /> <!-- query berat -->
</div>Jika RecentPosts melakukan query besar di mount(), seluruh halaman menunggunya — padahal komponen itu mungkin berada di bawah fold (di luar layar) atau bahkan tidak terlalu penting untuk dilihat pertama kali.
Parameter lazy pada tag komponen membuat Livewire melewati render awal komponen tersebut:
<div>
<h1>Dashboard</h1>
<livewire:recent-posts lazy />
<livewire:popular-posts lazy />
</div>Komponen akan dimuat saat ia masuk viewport (user scroll ke posisinya). Sementara itu, Livewire menampilkan placeholder — biasanya area kosong dengan animasi loading.
Terkadang komponen tidak perlu menunggu viewport — misalnya konten penting yang harus muncul, tapi tidak boleh menghambat initial render:
<livewire:revenue defer />Perbedaan keduanya:
| Mode | Kapan dimuat | Kapan dipakai |
|---|---|---|
lazy | Saat masuk viewport | Konten di bawah fold |
defer | Segera setelah halaman pertama selesai | Konten penting tapi berat |
Jika sebuah komponen selalu berat, tetapkan default-nya agar semua pemakaian otomatis lazy:
<?php
namespace App\Livewire;
use Livewire\Attributes\Lazy;
use Livewire\Component;
use App\Models\Post;
#[Lazy]
class PopularPosts extends Component
{
public function render()
{
return view('livewire.popular-posts', [
'posts' => Post::popular()->limit(5)->get(),
]);
}
}Sekarang <livewire:popular-posts /> otomatis lazy di mana pun dirender. Untuk defer default, gunakan #[Defer]. Opsional, kalian bisa menonaktifkan per penggunaan: <livewire:popular-posts :lazy="false" />.
Saat komponen lazy masih menunggu dimuat, Livewire menampilkan placeholder. Kustomisasi dengan method placeholder() di komponen:
#[Lazy]
class PopularPosts extends Component
{
public function placeholder(array $params = [])
{
return <<<'HTML'
<div class="animate-pulse bg-gray-100 h-40 rounded">
Memuat postingan populer...
</div>
HTML;
}
}Di view, placeholder bisa menggunakan directive @placeholder untuk layout yang lebih kaya. Placeholder yang baik: area dengan ukuran mendekati konten akhir, supaya layout shift minimal saat konten asli masuk.
Tip
Aturan praktisnya: komponen yang menjalankan query berat atau melakukan panggilan eksternal layak di-lazy-load jika tidak dibutuhkan di atas fold. Dashboard dengan 3-5 komponen statistik adalah kandidat sempurna. Komponen ringan justru tidak perlu lazy — menambahnya hanya menambah request.
wire:init adalah directive untuk menjalankan action segera setelah komponen pertama kali di-render di client:
<div wire:init="loadStats">
<h1>Statistik</h1>
<!-- ... -->
</div>public bool $loaded = false;
public array $stats = [];
public function loadStats()
{
$this->stats = StatsService::heavyComputation();
$this->loaded = true;
}Berbeda dengan query di mount() yang menunda render server, wire:init membuat halaman tampil dulu lalu menjalankan aksi berat sebagai respons terpisah. Kombinasinya dengan lazy loading sangat efektif: komponen lazy dimuat on-demand, dan di dalamnya wire:init menjalankan aksi berat tanpa menghalangi placeholder.
Pendekatan berurutan untuk dashboard yang cepat:
lazy.defer — halaman utama tampil, konten menyusul.mount() ke wire:init bila hasilnya tidak dibutuhkan untuk kerangka halaman.#[Lazy]/#[Defer] default pada komponen yang selalu berat, agar tidak ada pemakaian yang lupa.Dengan langkah ini, initial response server menjadi kecil, dan user melihat konten hampir seketika.
mount() untuk data penting: jika data dibutuhkan untuk kerangka halaman, defer lebih tepat daripada lazy.wire:init untuk semua aksi: gunakan untuk aksi berat yang bisa ditunda, bukan untuk inisialisasi ringan.Inti yang harus dibawa pulang:
lazy = muat saat viewport; defer = muat segera setelah halaman pertama; keduanya mencegah komponen berat memblokir render awal.#[Lazy]/#[Defer] menetapkan default di level komponen.placeholder() untuk UX yang halus tanpa layout shift.wire:init memicu action setelah mount client-side — pasangan ideal untuk aksi berat.mount().Di episode 15 selanjutnya kita akan membahas Alpine.js integration — kombinasi Livewire (state server) dengan Alpine (x-data, x-show, objek $wire) untuk micro-interactions seperti modal, dropdown, dan animasi. Sampai jumpa di episode 15!