Livewire 4 ya está disponible y trae cambios significativos. En este artículo vamos a revisar las novedades más importantes, los breaking changes que debes tener en cuenta al migrar, y algunas opiniones personales sobre las nuevas características.
Requisitos
Los requisitos mínimos son PHP 8.1+ y Laravel 10+. Bastante accesibles. La instalación es directa con composer require livewire/livewire:^4.0 seguido de php artisan optimize:clear.
Breaking Changes de Alto Impacto
Estos son los cambios que probablemente te afecten si vienes de Livewire 3.
Configuración renombrada
En config/livewire.php, las claves layout y lazy_placeholder ahora se llaman component_layout y component_placeholder respectivamente.
Nuevo sistema de routing
Aunque la sintaxis tradicional Route::get('/dashboard', Dashboard::class) sigue funcionando, ahora se recomienda usar Route::livewire():
<?php
// Recomendado en v4
Route::livewire('/dashboard', Dashboard::class);
// Para componentes basados en vistas
Route::livewire('/dashboard', 'pages::dashboard');wire:model ya no escucha eventos hijos
Este es un cambio importante. Si tenías un wire:model en un contenedor que escuchaba eventos de inputs hijos, ahora necesitas añadir el modificador .deep:
<!-- ANTES (v3) - escuchaba eventos de hijos automáticamente -->
<div wire:model="value">
<input type="text">
</div>
<!-- AHORA (v4) - necesitas .deep para el mismo comportamiento -->
<div wire:model.deep="value">
<input type="text">
</div>Tags de componentes deben cerrarse
Los tags de componentes Livewire ahora deben cerrarse obligatoriamente:
<!-- Ya no funciona -->
<livewire:component-name>
<!-- Obligatorio en v4 -->
<livewire:component-name />wire:scroll renombrado
Si usabas wire:scroll, ahora es wire:navigate:scroll.
Islands: La Estrella de Livewire 4
Sin duda, Islands es la característica más destacada de esta versión. Permite crear regiones aisladas dentro de un componente que se actualizan de forma independiente, sin necesidad de crear componentes hijos.
El problema que resuelve
Imagina un dashboard con estadísticas de revenue (query costosa), lista de usuarios y un gráfico. En Livewire 3, si hacías click en "Refresh" en cualquier parte, todo el componente se re-renderizaba, incluyendo las queries costosas.
La alternativa era crear componentes hijos, pero eso implica gestionar props, eventos y más archivos.
La solución
<?php
use Livewire\Attributes\Computed;
use Livewire\Component;
new class extends Component {
#[Computed]
public function revenue()
{
// Query costosa
return Revenue::yearToDate();
}
};
?>
<div>
@island
<div>
Revenue: {{ $this->revenue }}
<button wire:click="$refresh">Refresh</button>
</div>
@endisland
<!-- Esto NO se re-renderiza cuando refrescas el island -->
<div>
<h2>Otra sección</h2>
<p>Este contenido permanece intacto</p>
</div>
</div>Cuando haces click en "Refresh", solo el island se actualiza. El resto del componente ni se toca.
Lazy loading y defer
Los islands soportan carga diferida. Con lazy: true el contenido carga cuando entra en el viewport (scroll). Con defer: true carga inmediatamente después del page load:
@island(lazy: true)
<div>{{ $this->expensiveData }}</div>
@endisland
@island(defer: true)
<div>{{ $this->otherData }}</div>
@endislandNamed islands
Puedes nombrar islands y triggearlos desde cualquier parte del componente:
@island(name: 'stats')
<div>{{ $this->stats }}</div>
@endisland
<button wire:click="$refresh" wire:island="stats">
Actualizar estadísticas
</button>Append y Prepend para infinite scroll
@island(name: 'feed')
@foreach ($this->posts as $post)
<x-post-card :post="$post" />
@endforeach
@endisland
<button wire:click.append="loadMore" wire:island="feed">
Cargar más
</button>Placeholder personalizado
@island(lazy: true)
@placeholder
<div class="animate-pulse">
<div class="h-32 bg-gray-200 rounded"></div>
</div>
@endplaceholder
<div>{{ $this->revenue }}</div>
@endislandPor qué Islands es tan importante
Islands resuelve elegantemente un problema real: obtener el rendimiento de componentes pequeños sin la complejidad de crearlos. No necesitas gestionar props ni eventos porque todo sigue en el mismo componente. Además, el lazy loading integrado permite diferir la carga de secciones pesadas de forma trivial.
Limitaciones de Islands
No tienen acceso a variables @php del template padre y no pueden usarse dentro de @foreach, @if u otras estructuras de control. Si necesitas un loop, ponlo dentro del island.
Para más información, consulta el artículo Livewire 4 Islands.
Nuevas Formas de Crear Componentes
Livewire 4 introduce tres formas de crear componentes.
Single-File Components (SFC)
Es el formato por defecto en v4. PHP y Blade en el mismo archivo, usando el prefijo ⚡ en el nombre:
<?php
// resources/views/livewire/⚡counter.blade.php
use Livewire\Component;
new class extends Component {
public int $count = 0;
public function increment(): void
{
$this->count++;
}
};
?>
<div>
<h1>{{ $count }}</h1>
<button wire:click="increment">+</button>
</div>Multi-File Components (MFC)
Clase PHP en app/Livewire y vista en resources/views/livewire. Se crean con php artisan make:livewire counter --mfc.
View-Based Components
Solo una vista Blade sin clase PHP asociada. Útil para componentes muy simples.
Mi opinión personal
Prefiero los componentes tradicionales basados en clases (multi-file). La separación de responsabilidades es más clara, el IDE funciona mejor, y el código es más fácil de navegar y mantener. Los SFC pueden parecer convenientes, pero en proyectos reales la claridad gana.
Acciones Asíncronas
Permite ejecutar acciones en paralelo sin bloquear otras peticiones:
<?php
use Livewire\Attributes\Async;
#[Async]
public function logActivity(): void
{
// Se ejecuta sin bloquear
}<button wire:click.async="logActivity">Track</button>Precaución: Las acciones async pueden causar race conditions si modifican propiedades compartidas.
Lazy y Defer para Componentes
Además de los islands, puedes aplicar lazy y defer a componentes completos.
El atributo #[Lazy] hace que el componente cargue cuando entra en el viewport. El atributo #[Defer] hace que cargue inmediatamente después del page load.
También puedes usarlos en la vista con <livewire:component lazy /> o <livewire:component defer />.
Para cargar múltiples componentes en una sola petición, usa lazy.bundle:
<livewire:stats lazy.bundle />
<livewire:chart lazy.bundle />wire:sort - Drag & Drop Nativo
Por fin tenemos drag & drop integrado sin librerías externas:
<?php
public function updateOrder($item, $position): void
{
$todo = Todo::find($item);
$todo->update(['order' => $position]);
}<ul wire:sort="updateOrder">
@foreach ($todos as $todo)
<li wire:sort:item="{{ $todo->id }}" wire:key="{{ $todo->id }}">
{{ $todo->title }}
</li>
@endforeach
</ul>Soporta handles específicos con wire:sort:handle, elementos que no triggerean drag con wire:sort:ignore, y drag entre grupos con wire:sort:group.
wire:intersect - Intersection Observer
Ejecuta acciones cuando un elemento entra o sale del viewport:
<div wire:intersect="loadMore">...</div>
<div wire:intersect.once="trackView">...</div>
<div wire:intersect:leave="pauseVideo">...</div>
<div wire:intersect.half="loadMore">...</div>
<div wire:intersect.full="startAnimation">...</div>Ideal para analytics, lazy loading de contenido, o infinite scroll.
Otros Cambios Notables
wire:ref
Nueva forma de referenciar elementos para usar en JavaScript:
<div wire:ref="modal">...</div>Modificadores nuevos
El modificador .renderless ejecuta una acción sin re-renderizar el componente. El modificador .preserve-scroll mantiene la posición de scroll.
$errors en JavaScript
Ahora puedes acceder a los errores de validación desde JavaScript:
<div wire:show="$errors.has('email')">
<span wire:text="$errors.first('email')"></span>
</div>Mejoras de rendimiento
El polling con wire:poll ya no bloquea otras peticiones, wire:model.live ejecuta peticiones en paralelo, y smart_wire_keys viene activado por defecto.
Migración desde Volt
Si usabas Volt, ahora puedes migrar a Livewire nativo. Cambia use Livewire\Volt\Component por use Livewire\Component, elimina VoltServiceProvider y ejecuta composer remove livewire/volt. Los componentes Volt class-based funcionan sin modificación adicional.
Resumen de PHP Attributes
Attribute | Descripción |
|---|---|
| Ejecutar acción en paralelo |
| Propiedad computada/memoizada |
| Cargar después del page load |
| Cargar al entrar en viewport |
| Propiedad no modificable desde cliente |
| Propiedad bindeable con wire:model en componente padre |
| Listener de eventos |
| Props reactivos desde componente padre |
| Acción sin re-render |
| Persistir en sesión |
| Título de página |
| Persistir en query string |
| Reglas de validación inline |
Conclusión
Livewire 4 es una actualización sólida. Islands es claramente la estrella de esta versión, resolviendo elegantemente el problema de rendimiento en componentes grandes sin añadir complejidad.
Los Single-File Components son interesantes para quien venga de Vue o React, pero personalmente sigo prefiriendo los componentes basados en clases tradicionales por su mejor integración con el IDE y la separación clara de responsabilidades.
La migración desde v3 es relativamente sencilla. Los breaking changes más importantes son el cambio en wire:model (que ahora requiere .deep para escuchar eventos de hijos) y la necesidad de cerrar los tags de componentes.
Para más información, consulta la documentación oficial de Livewire 4.
Curso Laravel 12
Completo 2026
El único curso 100% actualizado que incluye Laravel 12, Livewire 3, Vue 3, React 19 e Inertia 2. Aprende con proyectos reales y las últimas funcionalidades.
star Incluido en cualquier suscripción