SKILL.md
$27
Data Fetching
- Prefer
await useFetch()for SSR-safe API reads in pages and components. It forwards server-fetched data into the Nuxt payload and avoids a second fetch on hydration.
- Use
useAsyncData()when the fetcher is not a simple$fetch()call, when you need a custom key, or when you are composing multiple async sources.
- Give
useAsyncData()a stable key for cache reuse and predictable refresh behavior.
- Keep
useAsyncData()handlers side-effect free. They can run during SSR and hydration.
- Use
$fetch()for user-triggered writes or client-only actions, not top-level page data that should be hydrated from SSR.
- Use
lazy: true,useLazyFetch(), oruseLazyAsyncData()for non-critical data that should not block navigation. Handlestatus === 'pending'in the UI.
- Use
server: falseonly for data that is not needed for SEO or the first paint.
- Trim payload size with
pickand prefer shallower payloads when deep reactivity is unnecessary.
const route = useRoute()
const { data: article, status, error, refresh } = await useAsyncData(
() => `article:${route.params.slug}`,
() => $fetch(`/api/articles/${route.params.slug}`),
)
const { data: comments } = await useFetch(`/api/articles/${route.params.slug}/comments`, {
lazy: true,
server: false,
})
Route Rules
Prefer routeRules in nuxt.config.ts for rendering and caching strategy:
export default defineNuxtConfig({
routeRules: {
'/': { prerender: true },
'/products/**': { swr: 3600 },
'/blog/**': { isr: true },
'/admin/**': { ssr: false },
'/api/**': { cache: { maxAge: 60 * 60 } },
},
})
prerender: static HTML at build time
swr: serve cached content and revalidate in the background
isr: incremental static regeneration on supported platforms
ssr: false: client-rendered route
cacheorredirect: Nitro-level response behavior
Pick route rules per route group, not globally. Marketing pages, catalogs, dashboards, and APIs usually need different strategies.
Lazy Loading and Performance
- Nuxt already code-splits pages by route. Keep route boundaries meaningful before micro-optimizing component splits.
- Use the
Lazyprefix to dynamically import non-critical components.
- Conditionally render lazy components with
v-ifso the chunk is not loaded until the UI actually needs it.
- Use lazy hydration for below-the-fold or non-critical interactive UI.
<template>
<LazyRecommendations v-if="showRecommendations" />
<LazyProductGallery hydrate-on-visible />
</template>
- For custom strategies, use
defineLazyHydrationComponent()with a visibility or idle strategy.
- Nuxt lazy hydration works on single-file components. Passing new props to a lazily hydrated component will trigger hydration immediately.
- Use
NuxtLinkfor internal navigation so Nuxt can prefetch route components and generated payloads.
Review Checklist
- First SSR render and hydrated client render produce the same markup
- Page data uses
useFetchoruseAsyncData, not top-level$fetch
- Non-critical data is lazy and has explicit loading UI
- Route rules match the page's SEO and freshness requirements
- Heavy interactive islands are lazy-loaded or lazily hydrated