Why Islands and Lazy Loading Matter
A Livewire page that boots five components on the initial request pays the full PHP hydration cost upfront — database queries, authorization checks, and serialization all happen before the first byte reaches the browser. Livewire v3 ships three complementary tools to break that cost apart: lazy components, deferred properties, and the island pattern (composing independent component trees). Used together they let you render a fast, mostly-static shell and hydrate interactive regions only when the browser is ready.
Lazy Components: Hydrate After Paint
Adding #[Lazy] to a component class tells Livewire to render a placeholder on the server and fire a subsequent network request to hydrate the real component after the page loads.
<?php
namespace App\Livewire;
use Livewire\Attributes\Lazy;
use Livewire\Component;
#[Lazy]
class RevenueChart extends Component
{
public function render()
{
return view('livewire.revenue-chart', [
'data' => $this->buildChartData(), // expensive query
]);
}
}
The placeholder is whatever your placeholder() method (or a placeholder.blade.php sibling view) returns:
public function placeholder(array $params = []): \Illuminate\View\View
{
return view('livewire.placeholders.chart-skeleton');
}
Pitfall: #[Lazy] fires a full Livewire request per component. If you have ten lazy components on one page you get ten extra HTTP round-trips. Batch related data into a single component or use #[Lazy(isolate: false)] to merge all lazy requests on a page into one.
#[Lazy(isolate: false)]
class RevenueChart extends Component { /* ... */ }
With isolate: false, Livewire groups all non-isolated lazy components into a single batched request — a significant win on dashboard pages.
Deferred Properties
Sometimes you want the component to hydrate immediately but defer loading a specific expensive property. The #[Deferred] attribute (available from Livewire 3.4+) does exactly that:
use Livewire\Attributes\Deferred;
class OrdersTable extends Component
{
#[Deferred]
public array $summary = [];
public function mount(): void
{
// $this->summary is NOT populated here on first render
}
public function loadSummary(): void
{
$this->summary = Order::query()->selectRaw('...')->get()->toArray();
}
}
In the Blade template you trigger the load via a lifecycle hook or a user action, keeping the initial render cheap.
The Island Pattern: Independent Component Trees
An "island" is simply a Livewire component that owns its own state and does not share Livewire wire-model bindings with its parent. The practical benefit is isolation: re-rendering one island does not trigger a diff on sibling islands.
{{-- resources/views/dashboard.blade.php --}}
<div class="grid grid-cols-3 gap-6">
<livewire:stats-card :key="'stats'" />
<livewire:activity-feed :key="'feed'" />
<livewire:quick-actions :key="'actions'" />
</div>
Always provide explicit :key values. Without them Livewire may morph the wrong DOM node when the parent re-renders, causing flicker or lost state.
Combine islands with #[Lazy(isolate: false)] for a dashboard that renders a static shell instantly and hydrates all islands in one batched request:
#[Lazy(isolate: false)]
class StatsCard extends Component { /* ... */ }
#[Lazy(isolate: false)]
class ActivityFeed extends Component { /* ... */ }
#[Lazy(isolate: false)]
class QuickActions extends Component { /* ... */ }
Skeleton Placeholders Without Extra Views
For quick prototyping you can return an inline placeholder without a dedicated view file:
public function placeholder(): string
{
return <<<'HTML'
<div class="animate-pulse h-48 bg-gray-100 rounded-xl"></div>
HTML;
}
This keeps the component self-contained and avoids view proliferation.
Key Takeaways
- Use
#[Lazy]to defer expensive component hydration until after first paint. - Set
isolate: falseon dashboards to batch all lazy requests into one HTTP call. #[Deferred]properties let a component hydrate cheaply and load heavy data on demand.- Explicit
:keybindings on island components prevent morph collisions. - Measure with browser DevTools Network tab — count Livewire requests before and after to validate gains.