Lazy Loading
Livewire le permite cargar componentes que de otro modo ralentizarían la carga inicial de la página.
Por ejemplo, imagine que tiene un componente Revenue
que contiene una consulta lenta a la base de datos en mount()
:
<?php
namespace App\Livewire;
use Livewire\Component;use App\Models\Transaction;
class Revenue extends Component{ public $amount;
public function mount() { // Query de la base de datos muy lenta $this->amount = Transaction::monthToDate()->sum('amount'); }
public function render() { return view('livewire.revenue'); }}
<div> Revenue this month: {{ $amount }}</div>
Sin la carga diferida(lazy loading), este componente retrasaría la carga de toda la página y ralentizaría toda la aplicación.
Para activar la carga lenta, puede pasar el parámetro lazy
al componente:
<livewire:revenue lazy />
Ahora, en lugar de cargar el componente inmediatamente, Livewire omitirá este componente, cargando la página sin él. Entonces, cuando el componente sea visible en la ventana gráfica, Livewire hará una petición de red para cargar completamente este componente en la página.
Renderización del marcador de posición HTML
Por defecto, Livewire insertará un <div></div>
vacío para su componente antes de que se cargue completamente. Como el componente será inicialmente invisible para los usuarios, puede ser chocante cuando el componente aparezca de repente en la página.
Para indicar a los usuarios que el componente se está cargando, puede definir un método placeholder()
para mostrar cualquier tipo de HTML de marcador de posición que desee, incluidos los marcadores de carga y los marcadores de posición de esqueleto:
<?php
namespace App\Livewire;
use Livewire\Component;use App\Models\Transaction;
class Revenue extends Component{ public $amount;
public function mount() { // Query de la base de datos lenta $this->amount = Transaction::monthToDate()->sum('amount'); }
public function placeholder() { return <<<'HTML' <div> <!-- Spinner de cargando... --> <svg>...</svg> </div> HTML; }
public function render() { return view('livewire.revenue'); }}
Dado que el componente anterior especifica un “marcador de posición(placeholder)” devolviendo HTML desde un método placeholder()
, el usuario verá un spinner de carga SVG en la página hasta que el componente esté completamente cargado.
Renderizar un marcador de posición (placeholder) a través de una vista
Para cargadores más complejos (como esqueletos) puedes devolver una vista desde placeholder()
de forma similar a render()
.
public function placeholder(array $params = []){ return view('livewire.placeholders.skeleton', $params);}
Cualquier parámetro del componente que se está cargando perezosamente estará disponible como un argumento $params
pasado al método placeholder()
.
Carga diferida fuera del Viewport
Por defecto, los componentes cargados de forma diferida no se cargan completamente hasta que entran en la ventana gráfica del navegador(viewport), por ejemplo cuando un usuario se desplaza hasta uno de ellos.
Si prefiere cargar todos los componentes de una página en cuanto ésta se carga, sin esperar a que entren en la ventana gráfica, puede hacerlo introduciendo “on-load” en el parámetro lazy
:
<livewire:revenue lazy="on-load" />
Ahora este componente se cargará después de que la página esté lista sin esperar a que esté dentro del viewport.
Pasar props
En general, puede tratar los componentes lazy
igual que los componentes normales, ya que aún puede pasarles datos desde fuera.
Por ejemplo, este es un escenario en el que puede pasar un intervalo de tiempo al componente Revenue
desde un componente padre:
<input type="date" wire:model="start"><input type="date" wire:model="end">
<livewire:revenue lazy :$start :$end />
Puede aceptar estos datos en mount()
como cualquier otro componente:
<?php
namespace App\Livewire;
use Livewire\Component;use App\Models\Transaction;
class Revenue extends Component{ public $amount;
public function mount($start, $end) { // Una SQL aún más lenta $this->amount = Transactions::between($start, $end)->sum('amount'); }
public function placeholder() { return <<<'HTML' <div> <!-- Nuestro spinner o lo que queramos --> <svg>...</svg> </div> HTML; }
public function render() { return view('livewire.revenue'); }}
Sin embargo, a diferencia de la carga de un componente normal, un componente perezoso
tiene que serializar o deshidratar
(dehydrate) cualquier propiedad pasada y almacenarla temporalmente en el lado del cliente hasta que el componente esté completamente cargado.
Por ejemplo, es posible que desee pasar un modelo Eloquent al componente Revenue
de la siguiente manera:
<livewire:revenue lazy :$user />
En un componente normal, el modelo PHP en memoria $user
sería pasado al método mount()
de Revenue
. Sin embargo, como no ejecutaremos mount()
hasta la siguiente petición de red, Livewire serializará internamente $user
a JSON y luego lo volverá a consultar desde la base de datos antes de que se gestione la siguiente petición.
Típicamente, esta serialización no debería causar ninguna diferencia de comportamiento en su aplicación.
Lazy Load por Defecto
Si desea imponer que todos los usos de un componente sean de carga lenta, puede añadir el atributo #[Lazy]
sobre la clase del componente:
<?php
namespace App\Livewire;
use Livewire\Component;use Livewire\Attributes\Lazy;
#[Lazy]class Revenue extends Component{ // ...}
Si desea anular la carga perezosa(lazy loading), puede establecer el parámetro lazy
en false
:
<livewire:revenue :lazy="false" />
Desactivar el aislamiento de peticiones(request)
Si hay varios componentes de carga diferida en la página, cada componente realizará una petición de red independiente, en lugar de agrupar cada actualización diferida en una única petición.
Si desea desactivar este comportamiento de aislamiento y, en su lugar, agrupar todas las actualizaciones en una única petición de red, puede hacerlo con el parámetro isolate: false
<?php
namespace App\Livewire;
use Livewire\Component;use Livewire\Attributes\Lazy;
#[Lazy(isolate: false)]class Revenue extends Component{ // ...}
Ahora, si hay diez componentes de Revenue
en la misma página, cuando ésta se cargue, las diez actualizaciones se agruparán y se enviarán al servidor como una única petición de red.
Aplicar lazy loading a Toda la Pagina (Full-page lazy loading)
Puede que quieras cargar componentes Livewire de página completa. Puede hacerlo llamando ->lazy()
en la ruta de esta forma:
Route::get('/dashboard', \App\Livewire\Dashboard::class)->lazy();
O, alternativamente, si hay un componente que se carga de forma perezosa por defecto, y desea optar por la carga perezosa, puede utilizar el siguiente parámetro enabled: false
:
Route::get('/dashboard', \App\Livewire\Dashboard::class)->lazy(enabled: false);
Vista por defecto del marcador de posición(placeholder)
Si quieres establecer una vista de marcador de posición(placeholder) por defecto para todos tus componentes puedes hacerlo haciendo referencia a la vista en el archivo de configuración /config/livewire.php:
'lazy_placeholder' => 'livewire.placeholder',
Ahora, cuando un componente es lazy-loaded y no se define placeholder()
, Livewire utilizará la vista Blade configurada (livewire.placeholder
en este caso.)
Deshabilitar la carga lenta para las pruebas
Al probar un componente perezoso(lazy), o una página con componentes perezosos anidados, es posible que desee desactivar el comportamiento “perezoso” para que pueda confirmar el comportamiento final renderizado. De lo contrario, esos componentes se renderizarían como sus marcadores de posición durante las pruebas.
Puede desactivar fácilmente la carga perezosa utilizando el ayudante de pruebas Livewire::withoutLazyLoading()
de la siguiente manera:
<?php
namespace Tests\Feature\Livewire;
use App\Livewire\Dashboard;use Livewire\Livewire;use Tests\TestCase;
class DashboardTest extends TestCase{ /** @test */ public function renders_successfully() { Livewire::withoutLazyLoading() ->test(Dashboard::class) ->assertSee(...); }}
Ahora, cuando el componente del panel de control se renderice para esta prueba, omitirá la renderización del marcador de placeholder()
y en su lugar renderizará el componente completo como si no se hubiera aplicado la carga diferida en absoluto.