フロントエンドのデータ取得で注目されている「SWR(Stale-While-Revalidate)」は、データを即時表示しながら、バックグラウンドで最新データを取得してUIを更新するアプローチです。Reactでは「swr」ライブラリが知られていますが、Vueでも同様の仕組みを自作して再現できます。本記事では、Vue 3 + Composition APIを用いて、SWRの考え方をVueアプリケーションに取り入れる方法を解説します。
SWRとは何か?
SWRは「古いデータ(Stale)を即座に表示しながら、非同期で新しいデータを取得し(Revalidate)、取得後に再描画する」というキャッシュ戦略です。これにより、UXを損なわずに最新データも維持できます。
VueでSWRを実装するためのステップ
以下のような流れでSWRを再現します。
- ローカルキャッシュを優先的に表示
- バックグラウンドでAPIを再取得
- 取得完了後、UIを更新
基本コードの実装例
以下の例では、`useSWR.js`というComposableを作成し、Vueコンポーネントから利用できるようにしています。
useSWR.js
import { ref } from 'vue';
const cache = new Map();
export function useSWR(key, fetcher) {
const data = ref(cache.get(key) || null);
const isLoading = ref(!cache.has(key));
const error = ref(null);
// 即時取得 → キャッシュがあれば即表示
if (!cache.has(key)) {
fetchData();
} else {
// バックグラウンドで再取得
fetchData();
}
async function fetchData() {
try {
const response = await fetcher();
cache.set(key, response);
data.value = response;
error.value = null;
} catch (err) {
error.value = err;
} finally {
isLoading.value = false;
}
}
return { data, isLoading, error };
}
使用例(MyComponent.vue)
<template>
<div>
<div v-if="isLoading">読み込み中...</div>
<div v-else-if="error">エラー: {{ error.message }}</div>
<div v-else>{{ data }}</div>
</div>
</template>
<script setup>
import { useSWR } from './useSWR';
const { data, isLoading, error } = useSWR('user', async () => {
const res = await fetch('https://jsonplaceholder.typicode.com/users/1');
if (!res.ok) throw new Error('取得に失敗しました');
return await res.json();
});
</script>
キャッシュの仕組みとリスク
この実装では、アプリ実行中のメモリ内にキャッシュを保持します。ページ遷移時に再利用されることで高速なUI体験が可能ですが、メモリリークや古いデータの保持には注意が必要です。
リアルタイム更新を組み合わせる場合
SWRは一度取得して終わりではなく、一定時間ごとに再取得したり、フォーカス時に再取得する設計とも相性が良いため、`setInterval()`や`visibilitychange`イベントとの併用も検討できます。
まとめ
VueにおけるSWRの再現は、簡易的なキャッシュと非同期再取得を組み合わせることで可能です。Vue特有のComposition APIを活かすことで、再利用性の高いデータ取得ロジックが構築できます。大規模なデータ処理が必要な場合は、Vue QueryやApollo Clientなどの導入も検討すると良いでしょう。