Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Nuxt 4 の Singleton Data Fetching Layer で 何が変わるのか
Search
Naoki Haba
October 25, 2025
2.5k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Nuxt 4 の Singleton Data Fetching Layer で 何が変わるのか
Vue Fes Japan 2025
https://vuefes.jp/2025/speaker/NaokiHaba
Naoki Haba
October 25, 2025
More Decks by Naoki Haba
See All by Naoki Haba
Vue Fes Japan の “作る側”に関わってみて
naokihaba
1
200
setup-vp GitLab対応の裏側
naokihaba
0
180
Vite+ Unified Toolchain for the Web
naokihaba
0
1k
Laravel+PHPStanで始める実践的静的解析入門
naokihaba
2
860
Webからモバイルへ Vue.js × Capacitor 活用事例
naokihaba
0
1.5k
Pinia Colada が実現するスマートな非同期処理
naokihaba
4
2.6k
unplugin-vue-routerで実現する Nuxt 風ファイルベースルーティング
naokihaba
1
290
VueUse: 5分で分かる Vue.js 開発の効率化術
naokihaba
5
4.6k
チームで始める_テスト文化のススメ
naokihaba
0
880
Featured
See All Featured
New Earth Scene 8
popppiees
4
2.7k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.7k
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
580
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
1
470
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Amusing Abliteration
ianozsvald
1
360
For a Future-Friendly Web
brad_frost
184
11k
Evolving SEO for Evolving Search Engines
ryanjones
0
330
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3.1k
Embracing the Ebb and Flow
colly
88
5.2k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
720
Transcript
Nuxt 4 の Singleton Data Fetching Layer で 何が変わるのか 2025.10.25
Vue Fes Japan 2025 View slides: naokihaba/talks
Naoki Haba naokihaba @naokihaba naohaba.bsky.social Software Engineer. Vue Fes Japan
2025 Core Staff
Nuxt 4 リリースから3 ヶ月 🙋 皆さんはもう Nuxt 4 を使い始めていますか? 今日は、Nuxt
4 で改善されたデータフェッチの仕組みについてお話しします
その前に、こんな経験ありませんか? ✗ 同じキーで呼び出しても複数回リクエストが発生 ✗ key が変わっても手動でwatch を書く必要がある ✗ キャッシュを使うタイミングを細かく制御できない ✗
不要なデータが残り続けてメモリリークのリスク ✅ Singleton Data Fetching Layer で解決
問題の詳細 Problem Details
Nuxt 3 までの挙動を見てみよう ComponentA.vue ComponentB.vue 同じキー 'user' を使っているが… const {
data } = useAsyncData('user', async () => { <script setup lang="ts"> console.log(' 🔵 ComponentA: リクエスト開始') const result = await $fetch('/api/users') return result }, { server: false }) </script> const { data } = useAsyncData('user', async () => { <script setup lang="ts"> console.log(' 🟢 ComponentB: リクエスト開始') const result = await $fetch('/api/users') return result }, { server: false }) </script> どうなると思いますか?
結果:2 回リクエストが実行される 😱 Console 🔵 ComponentA と 🟢 ComponentB の両方でログ
が出力される Network 同じ key: 'user' なのに 2 回のリクエストが発生
なぜ2 回実行される? 課題: 各コンポーネントで asyncData をコピーし、 refresh も新規作成 → ComponentA
と ComponentB で それぞれ handler が実行される Nuxt 3 の実装 const asyncData = { ...nuxtApp._asyncData[key] } // オブジェクトをコピー asyncData.refresh = () => handler(nuxtApp) // refresh 関数を新規作成 if (options.immediate) { initialFetch() // ← ここで各コンポーネントごとにフェッチが実行される // 各コンポーネントでの処理 // immediate: true (デフォルト)なら即実行 }
解決策 Solution
改善1: 同じkey でref インスタンスを共有 Before (Nuxt 3) After (Nuxt 4)
users1 !== users2 // 別々の ref // handler が 2 回実行 😢 const { data: users1 } = useAsyncData( 'users', () => $fetch('/api/users') ) const { data: users2 } = useAsyncData( 'users', () => $fetch('/api/users') ) users1 === users2 // 同じ ref // handler は 1 回だけ ✨ const { data: users1 } = useAsyncData( 'users', () => $fetch('/api/users') ) const { data: users2 } = useAsyncData( 'users', () => $fetch('/api/users') )
実装: _init フラグによる厳密な管理 ポイント _init フラグで 一度だけ初期化 を保証 既に初期化済みの場合は既存のインスタンスを使用 →
同じ key なら 同じ ref インスタンス を共有 if (!nuxtApp._asyncData[key.value]?._init) { initialFetchOptions.cachedData = options.getCachedData(key.value, nuxtApp, ...); nuxtApp._asyncData[key.value] = createAsyncData(nuxtApp, key.value, _handler, options, ...); } const initialFetch = () => nuxtApp._asyncData[key.value].execute(initialFetchOptions);
補足 Nuxt 3.17.2 から徐々に実装が進行 Singleton Data Fetching Layer の機能は一度にすべてが導入されたわけで はありません
Nuxt 3.17.2 から段階的に実装が開始され、Nuxt 4 で完成形となりました この期間に、ref の共有、reactive key のサポート、自動クリーンアップ などが順次追加されました 段階的な実装について
その他の改善点 Other Improvements
その他の改善点 1. getCachedData の拡張制御 すべてのデータ取得時に呼び出される 初回だけでなく、watch や refresh 時も キャッシュ戦略を柔軟に制御可能
2. Reactive key のサポート computed や ref を key に使用できる。 Reactive key が変わると自動的にデータを再取得 getCachedData: (key, nuxtApp, ctx) => { // ctx.cause で呼び出し元を判定 // 'initial' | 'watch' | 'refresh:manual' if (ctx.cause === 'initial') { return nuxtApp.payload.data[key] const { data } = useAsyncData('user', () => $fetch('/api/user'), { } return nuxtApp.static.data[key] } }) const userId = ref('1') const key = computed(() => `user-${userId.value}`) const { data } = useAsyncData(key, () => $fetch(`/api/users/${userId.value}`) userId.value = '2' // watch を書く必要がない! // key が変わると自動的にデータを再取得 ) // userId を変更すると自動的に再フェッチ
1. 自動データクリーンアップ 使われなくなったデータは自動的に削除される asyncData._deps++ if (data?._deps) { data._deps-- // 誰も参照していなければクリーンアップ
if (data._deps === 0) { data._off() // データを自動削除 } // 参照カウントで追跡 // コンポーネントがアンマウントされたら const unregister = (key) => { const data = nuxtApp._asyncData[key] } } onScopeDispose(() => { unregister(key.value) })
まとめ ✅ 同じ key で ref インスタンスを共有 ✅ Reactive key
のサポート ✅ getCachedData の拡張制御 ✅ 自動データクリーンアップ ✨ パフォーマンス向上 & メモリ管理の改善 Nuxt 4 Singleton Data Fetching Layer
ご清聴ありがとう ございました Slides: naokihaba/talks