---
title: "预渲染"
description: "Nuxt 允许页面在构建时静态渲染以提升某些性能或 SEO 指标"
canonical_url: "https://nuxt.zhcndoc.com/docs/4.x/getting-started/prerendering"
---
# 预渲染

> Nuxt 允许页面在构建时静态渲染以提升某些性能或 SEO 指标

Nuxt 允许将应用中的部分页面在构建时渲染。Nuxt 在请求这些页面时会提供预构建好的页面，而不是在运行时动态生成它们。

<read-more to="https://nuxt.zhcndoc.com/docs/4.x/guide/concepts/rendering" title="Nuxt 渲染模式">



</read-more>

## 基于爬虫的预渲染

使用 [`nuxt generate` 命令](https://nuxt.zhcndoc.com/docs/4.x/api/commands/generate)，通过 [Nitro](https://nuxt.zhcndoc.com/docs/4.x/guide/concepts/server-engine) 爬虫构建并预渲染应用。此命令类似于设置 `nitro.static` 选项为 `true` 的 `nuxt build`，或运行 `nuxt build --prerender`。

这会构建你的网站，启动一个 nuxt 实例，并且默认会预渲染根页面 `/`，以及该页面链接的任何站点页面、这些页面所链接的页面，依此类推。

<code-group sync="pm">

```bash [npm]
npx nuxt generate
```

```bash [yarn]
yarn nuxt generate
```

```bash [pnpm]
pnpm nuxt generate
```

```bash [bun]
bun x nuxt generate
```

```bash [deno]
deno x nuxt generate
```

</code-group>

你现在可以将 `.output/public` 目录部署到任意静态托管服务，或使用 `npx serve .output/public` 在本地预览。

静态构建和预渲染构建还会生成 `200.html` 和 `404.html` SPA 回退页面。请参阅[什么是 200.html 和 404.html？](https://nuxt.zhcndoc.com/docs/4.x/guide/concepts/rendering#what-are-200html-and-404html)。

Nitro 爬虫的工作原理：

1. 加载应用根路由（`/`）的 HTML、`~/pages` 目录中的任何非动态页面，以及 `prerender.routes` 数组中的其他路由。
2. 将 HTML 和 `_payload.json` 保存到 `~/.output/public/` 目录，以供静态托管。
3. 查找 HTML 中的所有锚点标签（`<a href="...">`），以导航到其他路由。
4. 对找到的每个锚点标签重复步骤 1-3，直到没有更多锚点标签可供爬取。

理解这一点很重要，因为未被任何可发现页面链接的页面无法被自动预渲染。

<read-more to="https://nuxt.zhcndoc.com/docs/4.x/api/commands/generate#nuxt-generate">

详细了解 `nuxt generate` 命令。

</read-more>

### 选择性预渲染

你可以在 `nuxt.config` 文件中手动指定 Nuxt 在构建期间获取并预渲染的路由，或忽略不想预渲染的路由（例如 `/dynamic`）：

```ts [nuxt.config.ts]twoslash
export default defineNuxtConfig({
  prerender: {
    routes: ['/user/1', '/user/2'],
    ignore: ['/dynamic'],
  },
})
```

你可以将此与 `crawlLinks` 选项结合使用，以预渲染爬虫无法发现的一组路由，例如你的 `/sitemap.xml` 或 `/robots.txt`：

```ts [nuxt.config.ts]twoslash
export default defineNuxtConfig({
  prerender: {
    crawlLinks: true,
    routes: ['/sitemap.xml', '/robots.txt'],
  },
})
```

顶层 `prerender` 选项适用于你使用的任何 `server.builder`。特定于构建器的选项（例如 Nitro 的 `concurrency` 或 `failOnError`）可以在 `nitro.prerender` 中设置。

<read-more to="https://nitro.zhcndoc.com/config#prerender">

在 Nitro 文档中阅读有关预渲染的更多内容。

</read-more>

最后，你也可以使用 routeRules 手动配置此行为。

```ts [nuxt.config.ts]twoslash
export default defineNuxtConfig({
  routeRules: {
    // 将 prerender 设置为 true 以配置该路由被预渲染
    '/rss.xml': { prerender: true },
    // 将其设置为 false 以配置该路由在预渲染时被跳过
    '/this-DOES-NOT-get-prerendered': { prerender: false },
    // /blog 下的所有内容都会被预渲染，只要它
    // 能从另一个页面链接到
    '/blog/**': { prerender: true },
  },
})
```

<read-more to="https://nitro.zhcndoc.com/config#routerules">

阅读有关 Nitro 的 `routeRules` 配置的更多内容。

</read-more>

作为简写，你也可以在页面文件中使用 [`defineRouteRules`](https://nuxt.zhcndoc.com/docs/4.x/api/utils/define-route-rules) 配置此项。

<read-more to="https://nuxt.zhcndoc.com/docs/4.x/guide/going-further/experimental-features#inlinerouterules" icon="i-lucide-star">

此功能为实验性功能，若要使用，必须在 `nuxt.config` 中启用 `experimental.inlineRouteRules` 选项。

</read-more>

```vue [app/pages/index.vue]
<script setup>
// 或在页面级别设置
defineRouteRules({
  prerender: true,
})
</script>

<template>
  <div>
    <h1>主页</h1>
    <p>在构建时预渲染</p>
  </div>
</template>
```

这将被转换为：

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  routeRules: {
    '/': { prerender: true },
  },
})
```

## 负载提取

当 Nuxt 在服务器上渲染页面时，它会将数据获取（[`useAsyncData`](https://nuxt.zhcndoc.com/docs/4.x/api/composables/use-async-data) 和 [`useFetch`](https://nuxt.zhcndoc.com/docs/4.x/api/composables/use-fetch)）以及应用状态（[`useState`](https://nuxt.zhcndoc.com/docs/4.x/api/composables/use-state)）的结果序列化到负载中，以便客户端可以在不重新获取数据的情况下进行 hydration。启用负载提取后，Nuxt 还会将此负载写入与路由 HTML 同目录下的 `_payload.json` 文件中：

- 预渲染路由会在构建时生成负载文件。
- 使用 [ISR 或 SWR 缓存](https://nuxt.zhcndoc.com/docs/4.x/guide/concepts/rendering#hybrid-rendering)的路由会在首次渲染路由时生成负载文件，即使是在混合（非静态）站点上也是如此。

在客户端导航期间，Nuxt 会获取目标路由的 `_payload.json` 文件，并重用提取出的数据，而不是在浏览器中再次运行数据获取。

你可以使用 [`experimental.payloadExtraction`](https://nuxt.zhcndoc.com/docs/4.x/api/nuxt-config#payloadextraction) 选项控制此行为：

- `'client'` - 负载会在初始渲染时内联到 HTML 中，并在客户端导航时提取到 `_payload.json` 文件中。首次加载时不会有额外的网络请求。
- `true` - 负载会在初始渲染和客户端导航时都提取到单独的 `_payload.json` 文件中。HTML 更小，且负载文件可以被 CDN 缓存，但首次加载会多一次请求。
- `false` - 禁用负载提取。负载始终内联在 HTML 中，不会生成 `_payload.json` 文件。

默认值为 `true`，如果设置了 `compatibilityVersion: 5` 则默认为 `'client'`。当设置 `ssr: false` 时，它会被强制设为 `false`。

```ts [nuxt.config.ts]twoslash
export default defineNuxtConfig({
  experimental: {
    payloadExtraction: 'client',
  },
})
```

还需要注意以下几个实际影响：

- 在完全静态站点上，客户端导航会重用构建时捕获的数据，因此在下一次重新构建之前，数据可能是过期的。
- 对于 ISR/SWR 路由，CDN 可以将负载文件与 HTML 一起缓存，从而提升已缓存路由的客户端导航性能。像 `pages/[...slug].vue` 这样的动态路由可以通过 `/**': { isr: true }` 等通配模式选择启用。
- 负载使用 [devalue](https://github.com/Rich-Harris/devalue) 序列化，因此自定义类型（例如类实例）需要带有自定义 reducer 和 reviver 的负载插件，才能在往返过程中保持不变。

<read-more to="https://nuxt.zhcndoc.com/docs/4.x/api/composables/use-nuxt-app#payload" title="负载 reducer 和 reviver">



</read-more>

## 运行时预渲染配置

### `prerenderRoutes`

你可以在 [Nuxt 上下文](https://nuxt.zhcndoc.com/docs/4.x/guide/going-further/nuxt-app#the-nuxt-context)中于运行时使用此功能，为 Nitro 添加更多要预渲染的路由。

```vue [app/pages/index.vue]
<script setup>
prerenderRoutes(['/some/other/url'])
prerenderRoutes('/api/content/article/my-article')
</script>

<template>
  <div>
    <h1>这将在预渲染时为其他路由注册预渲染</h1>
  </div>
</template>
```

<read-more to="https://nuxt.zhcndoc.com/docs/4.x/api/utils/prerender-routes" title="prerenderRoutes">



</read-more>

### `prerender:routes` Nuxt 钩子

这个钩子在预渲染之前被调用，用于注册额外的路由。

```ts [nuxt.config.ts]
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 钩子

该钩子在预渲染过程中对每个路由分别调用。你可以用它对每个被预渲染的路由进行更精细的处理。

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  nitro: {
    hooks: {
      'prerender:generate' (route) {
        if (route.route?.includes('private')) {
          route.skip = true
        }
      },
    },
  },
})
```


## Sitemap

See the full [sitemap](https://nuxt.zhcndoc.com/sitemap.md) for all pages.
