docs/1.getting-started/15.prerendering.md
Nuxt allows for select pages from your application to be rendered at build time. Nuxt will serve the prebuilt pages when requested instead of generating them on the fly.
:read-more{title="Nuxt rendering modes" to="/docs/4.x/guide/concepts/rendering"}
Use the nuxt generate command to build and pre-render your application using the Nitro crawler. This command is similar to nuxt build with the nitro.static option set to true, or running nuxt build --prerender.
This will build your site, stand up a nuxt instance, and, by default, prerender the root page / along with any of your site's pages it links to, any of your site's pages they link to, and so on.
::code-group{sync="pm"}
npx nuxt generate
yarn nuxt generate
pnpm nuxt generate
bun x nuxt generate
deno x nuxt generate
::
You can now deploy the .output/public directory to any static hosting service or preview it locally with npx serve .output/public.
Static and prerender builds also emit 200.html and 404.html SPA fallbacks. See What are 200.html and 404.html?.
Working of the Nitro crawler:
/), any non-dynamic pages in your ~/pages directory, and any other routes in the nitro.prerender.routes array._payload.json to the ~/.output/public/ directory to be served statically.<a href="...">) in the HTML to navigate to other routes.This is important to understand since pages that are not linked to a discoverable page can't be pre-rendered automatically.
::read-more{to="/docs/4.x/api/commands/generate#nuxt-generate"}
Read more about the nuxt generate command.
::
You can manually specify routes that Nitro will fetch and pre-render during the build or ignore routes that you don't want to pre-render like /dynamic in the nuxt.config file:
// @errors: 2353
export default defineNuxtConfig({
nitro: {
prerender: {
routes: ['/user/1', '/user/2'],
ignore: ['/dynamic'],
},
},
})
You can combine this with the crawlLinks option to pre-render a set of routes that the crawler can't discover like your /sitemap.xml or /robots.txt:
// @errors: 2353
export default defineNuxtConfig({
nitro: {
prerender: {
crawlLinks: true,
routes: ['/sitemap.xml', '/robots.txt'],
},
},
})
Setting nitro.prerender to true is similar to nitro.prerender.crawlLinks to true.
::read-more{to="https://nitro.build/config#prerender"} Read more about pre-rendering in the Nitro documentation. ::
Lastly, you can manually configure this using routeRules.
export default defineNuxtConfig({
routeRules: {
// Set prerender to true to configure it to be prerendered
'/rss.xml': { prerender: true },
// Set it to false to configure it to be skipped for prerendering
'/this-DOES-NOT-get-prerendered': { prerender: false },
// Everything under /blog gets prerendered as long as it
// is linked to from another page
'/blog/**': { prerender: true },
},
})
::read-more{to="https://nitro.build/config#routerules"}
Read more about Nitro's routeRules configuration.
::
As a shorthand, you can also configure this in a page file using defineRouteRules.
::read-more{to="/docs/4.x/guide/going-further/experimental-features#inlinerouterules" icon="i-lucide-star"}
This feature is experimental and in order to use it you must enable the experimental.inlineRouteRules option in your nuxt.config.
::
<script setup>
// Or set at the page level
defineRouteRules({
prerender: true,
})
</script>
<template>
<div>
<h1>Homepage</h1>
<p>Pre-rendered at build time</p>
</div>
</template>
This will be translated to:
export default defineNuxtConfig({
routeRules: {
'/': { prerender: true },
},
})
When Nuxt renders a page on the server, it serializes the results of your data fetching (useAsyncData and useFetch) and app state (useState) into a payload so the client can hydrate without re-fetching. With payload extraction enabled, Nuxt also writes this payload to a _payload.json file alongside the route's HTML:
During client-side navigation, Nuxt fetches the _payload.json file for the destination route and reuses the extracted data instead of running the data fetching again in the browser.
You can control this behavior with the experimental.payloadExtraction option:
'client' - The payload is inlined in the HTML for the initial render and extracted to _payload.json files for client-side navigation. There is no extra network request on first load.true - The payload is extracted to a separate _payload.json file for both the initial render and client-side navigation. The HTML is smaller and the payload file can be cached by a CDN, at the cost of one extra request on first load.false - Payload extraction is disabled. The payload is always inlined in the HTML and no _payload.json files are generated.The default is true, or 'client' when compatibilityVersion: 5 is set. It is forced to false when ssr: false is set.
export default defineNuxtConfig({
experimental: {
payloadExtraction: 'client',
},
})
A few practical consequences to be aware of:
pages/[...slug].vue can opt in with glob patterns such as '/**': { isr: true }.:read-more{title="Payload reducers and revivers" to="/docs/4.x/api/composables/use-nuxt-app#payload"}
prerenderRoutesYou can use this at runtime within a Nuxt context to add more routes for Nitro to prerender.
<script setup>
prerenderRoutes(['/some/other/url'])
prerenderRoutes('/api/content/article/my-article')
</script>
<template>
<div>
<h1>This will register other routes for prerendering when prerendered</h1>
</div>
</template>
:read-more{title="prerenderRoutes" to="/docs/4.x/api/utils/prerender-routes"}
prerender:routes Nuxt hookThis is called before prerendering for additional routes to be registered.
export default defineNuxtConfig({
hooks: {
async 'prerender:routes' (ctx) {
const { pages } = await fetch('https://api.some-cms.com/pages').then(
res => res.json(),
)
for (const page of pages) {
ctx.routes.add(`/${page.name}`)
}
},
},
})
prerender:generate Nitro hookThis is called for each route during prerendering. You can use this for fine-grained handling of each route that gets prerendered.
export default defineNuxtConfig({
nitro: {
hooks: {
'prerender:generate' (route) {
if (route.route?.includes('private')) {
route.skip = true
}
},
},
},
})