Best way to fetch and access api calls that are required for a large part of the site?
Have a situation in which we need to get user data or feature flags that is heavily checked across the site. So far we are using pinia to store this data and access it but was looking for ways to optimising the fetching of this data a bit. We need this data for basically every page. Couple of options here and was wondering if there was any thoughts on it:
1. Vue plugins - create a plugin that fetches and stores the data via composable/pinia that is used when the app is created/mounted?
2. Route guards - fetching the data via middleware? We can check here if it exists first before fetching it so it doesn't happen on every transition.
3. Put the requests in app.vue and handle it there?
Thanks for your help
2 Replies
Hi @polarkarate. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
For data like user info or feature flags that are required across most (or all) pages in a Nuxt app, the best approach is to fetch the data once and make it available globally, while ensuring you avoid unnecessary repeated requests and maximize SSR/client hydration efficiency. Here’s how the options you mentioned compare, based on Nuxt’s official recommendations:
---
1. Fetching in
The most straightforward and Nuxt-recommended approach is to fetch your global data in
app.vue
Recommended: Placing your data-fetching logic in app.vue
is a common and effective pattern. You can use useFetch
or useAsyncData
in app.vue
to fetch the data once during SSR, and the result will be included in the Nuxt payload and hydrated on the client. This avoids double-fetching and ensures the data is available before any page renders. You can then provide this data to Pinia or a composable for easy access throughout your app.
Example:
You can then access this data in other components using useNuxtData('user')
or by initializing your Pinia store with it. This approach is similar to the old nuxtServerInit
pattern from Nuxt 2 and is officially recommended for initializing global state with async data Nuxt State Management.
---
2. Vue Plugins
You can create a plugin that fetches the data and stores it in a Pinia store or a composable. This is also a valid approach, especially if you want to encapsulate logic or add custom fetchers (e.g., with authentication headers). However, you should ensure the plugin runs at the right lifecycle stage (typically on app initialization) and that you avoid double-fetching by using callOnce
or similar logic Custom useFetch in Nuxt.
---
3. Route Middleware
Using route middleware to fetch data is possible, but it’s best suited for cases where you need to guard navigation based on the data (e.g., authentication checks). Middleware can check if the data exists and fetch it if not, but you must ensure you don’t trigger unnecessary requests on every navigation. Middleware is less ideal for global data that’s needed on every page, as it can complicate caching and hydration addRouteMiddleware.
---
Optimization Tips
- Cache and Share Data: Nuxt 4+ automatically shares payload data between pages during prerendering if you use consistent keys with useFetch
/useAsyncData
Shared Prerender Data.
- Access Cached Data: Use useNuxtData
to access already-fetched data by key, avoiding extra requests useNuxtData.
- Pinia Integration: You can hydrate your Pinia store with the fetched data in app.vue
or a plugin, then use the store everywhere.
---
Summary:The most straightforward and Nuxt-recommended approach is to fetch your global data in
app.vue
using useFetch
or useAsyncData
, then provide it to your app via Pinia or a composable. This ensures SSR hydration, avoids double-fetching, and makes the data easily accessible everywhere Data Fetching State Management. Plugins are also valid for encapsulation, while middleware is best for navigation guards rather than global data.
Let me know if you’d like a code example for a specific setup!
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@1334094586280280108> Kapa.ai is still learning and improving, please let me know how I did by reacting below.