Inertia.js v2.0で追加された新機能を実際に実装してみた
概要
2週間前、Inertia.jsの2.0が正式にリリースされました。
今回のアップデート内容についてはこちらから確認することができます。
v2.0になって非同期リクエストの機能が大幅にサポートされました。
この記事では、新たに追加された以下の非同期リクエストの機能を実際に実装して動作とコードをまとめます。
- Polling
- Prefetching
- Deferred props
- Infinite scrolling
- Lazy loading data on scroll
動作環境
- Laravel11
- Vue3
Pooling
サーバーに定期的に通信してpropsを更新してくれます。
例として、propsで現在時刻を受け取りフロントで描画する簡単なコードを書きました。
Poolingのためのコードも非常にシンプルです。
<template>
<h1>current time is {{props.currentTime}}</h1>
</template>
<script setup lang="ts">
import {usePoll} from "@inertiajs/vue3";
const props = defineProps({
currentTime: {
type: String,
required: true,
}
})
usePoll(1000);
</script>
Prefetching
ページにアクセスする前にサーバーに通信を行いpropsを取得してくれます。
サーバーに通信を行うタイミングはコンポーネントが'mount' or 'hover' or 'click' された時の3つから複数選択可能です。デフォルトだと 'hover' になります。
例では一覧として表示されたユーザーリストをクリックして、ユーザーの詳細情報を表示する画面に遷移しています。
この時、ユーザーの詳細情報を表示するAPIにわざと2s程度のSleepを入れてPrefetchingされている時とされていない時の挙動の違いをわかりやすくしています。
import { Link } from '@inertiajs/vue3'
<Link href="/users" prefetch>Users</Link>
JavaScriptでハンドリングすることもできます。
router.prefetch(
'/users',
{ method: 'get', data: { page: 2 } },
)
router.prefetch(
'/users',
{ method: 'get', data: { page: 2 } },
{ cacheFor: '1m' },
)
もしくは、
import { usePrefetch } from '@inertiajs/vue3'
const { lastUpdatedAt, isPrefetching, isPrefetched } = usePrefetch(
'/users',
{ method: 'get', data: { page: 2 } },
{ cacheFor: '1m' },
)
ここで、cacheという概念が登場します。
その名の通り、prefetchしたデータをキャッシュすることができます。
デフォルトでは、30secの間データがキャッシュされます。
cacheの時間は任意の時間に調整可能です。
Deferred props
特定のデータの読み込みをページレンダリングの後まで延期できます。
例では先にページのレンダリングを行い、レンダリング後にユーザーの詳細情報を取得しています。
class DeferController extends Controller
{
public function __invoke()
{
return Inertia::render('Example/Defer', [
'user' => Inertia::defer(function() {
Sleep::sleep(1);
return User::where('id', 1)->first();
}),
]);
}
}
<template>
<Deferred data="user">
<template #fallback>
<div>Loading...</div>
</template>
<div>
<h1>user data</h1>
<ul>
<li>{{user['id']}}</li>
<li>{{user['name']}}</li>
<li>{{user['email']}}</li>
</ul>
</div>
</Deferred>
</template>
<script setup>
import { Deferred } from '@inertiajs/vue3'
defineProps({
user: {
type: Object,
}
})
</script>
Infinite scrolling
ドキュメントには Infinite scrolling と書かれている箇所もありますが、Merging props
と書かれている箇所もあります。コード的にはpropsのマージです。
ただ、実際に試してみたところうまくinfinite scrollできませんでした。
リポジトリにバグ報告のissueが作成されており、バグの内容もこちらで再現した時と同じようだったのでissueが解決されればうまく機能すると思います。
Lazy loading data on scroll
コンポーネントが画面に表示された時にデータのリクエストを行う機能です。
例として水色の背景の箇所をスクロールするとサーバーから取得した文字が表示される実装をしてみました。
ドキュメントには直接書いていませんが、サーバーサイドではPartialReloadsを使用してデータを渡さないとlazy-loadingになりません。
<?php
namespace App\Http\Controllers\Example;
use App\Http\Controllers\Controller;
use Illuminate\Support\Sleep;
use Inertia\Inertia;
class LoadWhenVisibleController extends Controller
{
public function __invoke()
{
return Inertia::render('Example/LoadWhenVisible', [
'message' => Inertia::lazy(function() {
Sleep::sleep(2);
return 'viewed!!';
})
]);
}
}
<template>
<div class="load-when-visible">
<h1>LoadWhenVisible</h1>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<WhenVisible data="message">
<template #fallback>
<div>Loading...</div>
</template>
<div>
<p>{{message}}</p>
</div>
</WhenVisible>
</div>
</template>
<script setup>
import { WhenVisible } from '@inertiajs/vue3'
defineProps({
message: {
type: String,
}
})
</script>
<style scoped>
.load-when-visible {
width: 500px;
height: 300px;
background-color: deepskyblue;
overflow: scroll;
}
</style>
所感
今までInertia.jsで非同期でデータを扱うにはPartialReloadsしか存在しないと個人的には認識しています。
PartialReloads以外だとSPAのようにAPIに対してアクセスする方法しかなく、"APIを構築しなくていい"というInertia.jsの利点を活かすことができませんでした。
今回、Inertia.jsの機能に乗りながら、非同期でデータを扱うことができるようになりました。
Inertia.jsの利点を活かしつつ、非同期でデータを扱うユースケース(大量のデータ,レンダリング時間の有効活用など)を行えるようになり、Inertia.jsが合致するビジネスケースが増えたと感じました。
Discussion