遅延ロード
Livewireでは、初期ページロードを遅くする可能性のあるコンポーネントを遅延ロードできます。Livewire allows you to lazy load components that would otherwise slow down the initial page load.
例えば、Revenue
コンポーネントのmount()
に遅いデータベースクエリが含まれているとします。For example, imagine you have a Revenue
component which contains a slow database query in mount()
:
<?php
namespace App\Livewire;
use Livewire\Component;
use App\Models\Transaction;
class Revenue extends Component
{
public $amount;
public function mount()
{
// 遅いデータベースクエリ...
$this->amount = Transaction::monthToDate()->sum('amount');
}
public function render()
{
return view('livewire.revenue');
}
}
<div>
Revenue this month: {{ $amount }}
</div>
遅延ロードを使用しない場合、このコンポーネントはページ全体のロードを遅延させ、アプリケーション全体の動作が遅く感じられます。Without lazy loading, this component would delay the loading of the entire page and make your entire application feel slow.
遅延ロードを有効にするには、lazy
パラメータをコンポーネントに渡します。To enable lazy loading, you can pass the lazy
parameter into the component:
<livewire:revenue lazy />
これで、Livewire はコンポーネントをすぐにロードする代わりに、このコンポーネントをスキップし、コンポーネントなしでページをロードします。次に、コンポーネントがビューポートに表示されると、Livewire はネットワークリクエストを行い、このコンポーネントをページに完全にロードします。Now, instead of loading the component right away, Livewire will skip this component, loading the page without it. Then, when the component is visible in the viewport, Livewire will make a network request to fully load this component on the page.
この動作の無効化に関する詳細はこちら →[!info] Lazy requests are isolated by default Unlike other network requests in Livewire, lazy loading updates are isolated from each other when sent to the server. This keeps lazy loading fast, by loading each component in parallel when a page loads. Read more on disabling this behavior here →[#disabling-request-isolation]
Info: 遅延リクエストはデフォルトで分離されています Livewire の他のネットワークリクエストとは異なり、遅延ロードの更新は、サーバに送信される際に互いに分離されます。これにより、ページがロードされる際に各コンポーネントを並行してロードすることで、遅延ロードを高速に保ちます。
placeholder HTMLのレンダリングRendering placeholder HTML
デフォルトでは、Livewire はコンポーネントが完全にロードされる前に、空の <div></div>
を挿入します。コンポーネントは最初はユーザーには見えないため、コンポーネントが突然ページに表示されると、ぎこちなく感じられることがあります。By default, Livewire will insert an empty <div></div>
for your component before it is fully loaded. As the component will initially be invisible to users, it can be jarring when the component suddenly appears on the page.
コンポーネントがロード中であることをユーザーに知らせるには、placeholder()
メソッドを定義して、ロードスピナーやスケルトンプレースホルダーなど、任意の種類のプレースホルダーHTMLをレンダリングできます。To signal to your users that the component is being loaded, you can define a placeholder()
method to render any kind of placeholder HTML you like, including loading spinners and skeleton placeholders:
<?php
namespace App\Livewire;
use Livewire\Component;
use App\Models\Transaction;
class Revenue extends Component
{
public $amount;
public function mount()
{
// 遅いデータベースクエリ...
$this->amount = Transaction::monthToDate()->sum('amount');
}
public function placeholder()
{
return <<<'HTML'
<div>
<!-- Loading spinner... -->
<svg>...</svg>
</div>
HTML;
}
public function render()
{
return view('livewire.revenue');
}
}
上記のコンポーネントは、placeholder()
メソッドからHTMLを返すことで "placeholder" を指定しているため、コンポーネントが完全にロードされるまで、ユーザーには SVG ローディングスピナーがページに表示されます。Because the above component specifies a "placeholder" by returning HTML from a placeholder()
method, the user will see an SVG loading spinner on the page until the component is fully loaded.
[!warning] The placeholder and the component must share the same element type For instance, if your placeholder's root element type is a 'div,' your component must also use a 'div' element.
Warning! プレースホルダーとコンポーネントは同じ要素タイプを共有する必要があります たとえば、プレースホルダーのルート要素タイプが「div」の場合、コンポーネントも「div」要素を使用する必要があります。
ビュー経由でのプレースホルダーのレンダリングRendering a placeholder via a view
より複雑なローダー (スケルトンなど) の場合は、render()
と同様に、placeholder()
からview
を返すことができます。For more complex loaders (such as skeletons) you can return a view
from the placeholder()
similar to render()
.
public function placeholder(array $params = [])
{
return view('livewire.placeholders.skeleton', $params);
}
遅延ロードされるコンポーネントからのパラメータは、placeholder()
メソッドに渡される$params
引数として使用できます。Any parameters from the component being lazy loaded will be available as an $params
argument passed to the placeholder()
method.
ビューポート外での遅延ロードLazy loading outside of the viewport
デフォルトでは、遅延ロードされたコンポーネントは、ブラウザのビューポートに入るまで完全にロードされません。たとえば、ユーザーがコンポーネントまでスクロールする場合などです。By default, Lazy-loaded components aren't full loaded until they enter the browser's viewport, for example when a user scrolls to one.
ビューポートに入るのを待たずに、ページがロードされるとすぐにページのすべてのコンポーネントを遅延ロードする場合は、lazy
パラメータに "on-load" を渡すことで実行できます。If you'd rather lazy load all components on a page as soon as the page is loaded, without waiting for them to enter the viewport, you can do so by passing "on-load" into the lazy
parameter:
<livewire:revenue lazy="on-load" />
これで、このコンポーネントは、ビューポート内に入るのを待たずに、ページの準備ができた後にロードされます。Now this component will load after the page is ready without waiting for it to be inside the viewport.
プロパティの受け渡しPassing in props
一般に、lazy
コンポーネントは通常のコンポーネントと同じように扱うことができます。外部からデータを渡すことができるためです。In general, you can treat lazy
components the same as normal components, since you can still pass data into them from outside.
たとえば、親コンポーネントから Revenue
コンポーネントに時間間隔を渡すシナリオを次に示します。For example, here's a scenario where you might pass a time interval into the Revenue
component from a parent component:
<input type="date" wire:model="start">
<input type="date" wire:model="end">
<livewire:revenue lazy :$start :$end />
他のコンポーネントと同様に、mount()
でこのデータを受け入れることができます。You can accept this data in mount()
just like any other component:
<?php
namespace App\Livewire;
use Livewire\Component;
use App\Models\Transaction;
class Revenue extends Component
{
public $amount;
public function mount($start, $end)
{
// コストのかかるデータベースクエリ...
$this->amount = Transactions::between($start, $end)->sum('amount');
}
public function placeholder()
{
return <<<'HTML'
<div>
<!-- Loading spinner... -->
<svg>...</svg>
</div>
HTML;
}
public function render()
{
return view('livewire.revenue');
}
}
ただし、通常のコンポーネントのロードとは異なり、lazy
コンポーネントは渡されたすべてのプロパティをシリアル化または "デハイドレート" し、コンポーネントが完全にロードされるまでクライアント側に一時的に保存する必要があります。However, unlike a normal component load, a lazy
component has to serialize or "dehydrate" any passed-in properties and temporarily store them on the client-side until the component is fully loaded.
たとえば、次のようにEloquentモデルを Revenue
コンポーネントに渡すことができます。For example, you might want to pass in an Eloquent model to the Revenue
component like so:
<livewire:revenue lazy :$user />
通常のコンポーネントでは、実際のPHPインメモリ$user
モデルが Revenue
の mount()
メソッドに渡されます。ただし、次のネットワークリクエストまで mount()
を実行しないため、Livewire は内部的に $user
を JSON にシリアル化し、次のリクエストが処理される前にデータベースから再度クエリします。In a normal component, the actual PHP in-memory $user
model would be passed into the mount()
method of Revenue
. However, because we won't run mount()
until the next network request, Livewire will internally serialize $user
to JSON and then re-query it from the database before the next request is handled.
通常、このシリアル化によってアプリケーションの動作に違いが生じることはありません。Typically, this serialization should not cause any behavioral differences in your application.
デフォルトで遅延ロードLazy load by default
コンポーネントのすべての使用箇所を強制的に遅延ロードする場合は、コンポーネントクラスの上に #[Lazy]
属性を追加できます。If you want to enforce that all usages of a component will be lazy-loaded, you can add the #[Lazy]
attribute above the component class:
<?php
namespace App\Livewire;
use Livewire\Component;
use Livewire\Attributes\Lazy;
#[Lazy]
class Revenue extends Component
{
// ...
}
遅延ロードをオーバーライドする場合は、lazy
パラメータを false
に設定できます。If you want to override lazy loading you can set the lazy
parameter to false
:
<livewire:revenue :lazy="false" />
リクエストの分離を無効にするDisabling request isolation
ページに複数の遅延ロードされたコンポーネントがある場合、各コンポーネントは独立したネットワークリクエストを行います。各遅延アップデートが1つのリクエストにバンドルされるわけではありません。If there are multiple lazy-loaded components on the page, each component will make an independent network request, rather than each lazy update being bundled into a single request.
この分離動作を無効にして、代わりにすべての更新を1つのネットワークリクエストにバンドルする場合は、isolate: false
パラメータを使用できます。If you want to disable this isolation behavior and instead bundle all updates together in a single network request you can do so with the isolate: false
parameter:
<?php
namespace App\Livewire;
use Livewire\Component;
use Livewire\Attributes\Lazy;
#[Lazy(isolate: false)] // [tl! highlight]
class Revenue extends Component
{
// ...
}
これで、同じページに10個の Revenue
コンポーネントがある場合、ページのロード時に、10個の更新がすべてバンドルされ、単一のネットワークリクエストとしてサーバに送信されます。Now, if there are ten Revenue
components on the same page, when the page loads, all ten updates will be bundled and sent the server as single network request.
フルページ遅延ロードFull-page lazy loading
フルページの Livewire コンポーネントを遅延ロードしたい場合があります。これは、次のようにルートで ->lazy()
を呼び出すことで実行できます。You may want to lazy load full-page Livewire components. You can do this by calling ->lazy()
on the route like so:
Route::get('/dashboard', \App\Livewire\Dashboard::class)->lazy();
または、デフォルトで遅延ロードされるコンポーネントがあり、遅延ロードをオプトアウトする場合は、次の enabled: false
パラメータを使用できます。Or alternatively, if there is a component that is lazy-loaded by default, and you would like to opt-out of lazy-loading, you can use the following enabled: false
parameter:
Route::get('/dashboard', \App\Livewire\Dashboard::class)->lazy(enabled: false);
デフォルトのプレースホルダービューDefault placeholder view
すべてのコンポーネントにデフォルトのプレースホルダービューを設定する場合は、/config/livewire.php
設定ファイルでビューを参照することで実行できます。If you want to set a default placeholder view for all your components you can do so by referencing the view in the /config/livewire.php
config file:
'lazy_placeholder' => 'livewire.placeholder',
これで、コンポーネントが遅延ロードされ、placeholder()
が定義されていない場合、Livewire は設定された Blade ビュー (この場合は livewire.placeholder
) を使用します。Now, when a component is lazy-loaded and no placeholder()
is defined, Livewire will use the configured Blade view (livewire.placeholder
in this case.)
テストでの遅延ロードの無効化Disabling lazy loading for tests
遅延コンポーネント、またはネストされた遅延コンポーネントを含むページをユニットテストする場合、最終的なレンダリングされた動作をアサートできるように、"遅延" 動作を無効にすることができます。そうしないと、これらのコンポーネントはテスト中にプレースホルダーとしてレンダリングされます。When unit testing a lazy component, or a page with nested lazy components, you may want to disable the "lazy" behavior so that you can assert the final rendered behavior. Otherwise, those components would be rendered as their placeholders during your tests.
次のように、Livewire::withoutLazyLoading()
テストヘルパを使用して、遅延ロードを簡単に無効にできます。You can easily disable lazy loading using the Livewire::withoutLazyLoading()
testing helper like so:
<?php
namespace Tests\Feature\Livewire;
use App\Livewire\Dashboard;
use Livewire\Livewire;
use Tests\TestCase;
class DashboardTest extends TestCase
{
public function test_renders_successfully()
{
Livewire::withoutLazyLoading() // [tl! highlight]
->test(Dashboard::class)
->assertSee(...);
}
}
これで、このテストのためにダッシュボードコンポーネントがレンダリングされると、placeholder()
のレンダリングはスキップされ、遅延ロードがまったく適用されていないかのようにコンポーネント全体がレンダリングされます。Now, when the dashboard component is rendered for this test, it will skip rendering the placeholder()
and instead render the full component as if lazy loading wasn't applied at all.