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.4k
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
setup-vp GitLab対応の裏側
naokihaba
0
33
Vite+ Unified Toolchain for the Web
naokihaba
0
920
Laravel+PHPStanで始める実践的静的解析入門
naokihaba
2
820
Webからモバイルへ Vue.js × Capacitor 活用事例
naokihaba
0
1.5k
Pinia Colada が実現するスマートな非同期処理
naokihaba
4
2.5k
unplugin-vue-routerで実現する Nuxt 風ファイルベースルーティング
naokihaba
1
290
VueUse: 5分で分かる Vue.js 開発の効率化術
naokihaba
5
4.5k
チームで始める_テスト文化のススメ
naokihaba
0
870
不具合に立ち向かう テスト戦略 ~ NestJSで作るCI環境 ~
naokihaba
0
590
Featured
See All Featured
The Mindset for Success: Future Career Progression
greggifford
PRO
0
490
A better future with KSS
kneath
240
18k
Practical Orchestrator
shlominoach
191
12k
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
280
Darren the Foodie - Storyboard
khoart
PRO
3
3.9k
Heart Work Chapter 1 - Part 1
lfama
PRO
9
36k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
590
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
New Earth Scene 8
popppiees
3
2.6k
The Curious Case for Waylosing
cassininazir
1
500
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
240
Marketing to machines
jonoalderson
1
5.8k
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