预渲染

在构建时预渲染页面,以实现最佳性能并避免服务器上的 CPU 使用率。

使用 NuxtHub 时,您需要使用 nuxt build 构建您的应用程序,以便在部署应用程序时保持服务器。

但是,您也可以在构建时预渲染页面,以提高性能并避免服务器上的 CPU 使用率。

这得益于 **Nuxt 的混合渲染**,它允许为每个路由设置不同的缓存规则。

路由规则

全局

您可以在 nuxt.config.ts 文件中定义路由规则,以指定每个路由应如何渲染。

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

运行 nuxt build 时,Nuxt 将预渲染 / 路由并将 index.html 文件保存在输出目录中。

使用 NuxtHub 在 Cloudflare Pages 上部署时,它将直接从边缘提供预渲染的 HTML 文件,以实现最佳性能并避免服务器上的 CPU 使用率。

页面级

也可以使用页面组件中的 defineRouteRules 实用程序在页面级别定义路由规则。

pages/index.vue
<script setup lang="ts">
defineRouteRules({
  prerender: true
})
</script>

<template>
  <h1>Hello world!</h1>
</template>

这等效于我们在上面 nuxt.config.ts 文件中的示例。

注意

  • ~/pages/foo/bar.vue 中定义的规则将应用于 /foo/bar 请求。
  • ~/pages/foo/[id].vue 中的规则将应用于 /foo/** 请求。
由于这是一个实验性功能,您需要在您的 nuxt.config.ts 文件中使用 experimental: { inlineRouteRules: true } 来启用它。

动态预渲染

在某些情况下,您可能希望 Nuxt 在预渲染特定页面时预渲染其他页面。

这在预渲染博客索引页面时预渲染所有博客文章时很有用。要实现这一点,我们可以在页面组件中使用 prerenderRoutes 实用程序。

pages/blog/index.vue
<script setup lang="ts">
// Pre-render the /blog page
defineRouteRules({ prerender: true })

const { data: posts } = await useFetch('/api/posts')

// Tell Nuxt to pre-render all blog posts
prerenderRoutes(posts.value.map(post => `/blog/${post.slug}`))
</script>

重要的是告诉 Nuxt 使用 defineRouteRules 预渲染 /blog,我们也可以在 nuxt.config.ts 文件中全局执行此操作。

nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    // If not using `defineRouteRules` in the page component
    '/blog': { prerender: true }
  }
})

使用 Nuxt 模块

您还可以使用 本地 Nuxt 模块 来预渲染动态页面,如果您没有单个根页面(例如 /blog)但仍然需要预渲染特定路由(例如 /page-1/parent/page-2 等),这特别有用。

modules/prerender-routes.ts
import { defineNuxtModule, addPrerenderRoutes } from '@nuxt/kit'

export default defineNuxtModule({
  meta: {
    name: 'nuxt-prerender-routes',
  },
  async setup() {
    const pages = await getDynamicPages()
    addPrerenderRoutes(pages)
  },
})

async function getDynamicPages(): string[] {
  // Replace this function with the logic for retrieving the slugs for your pages.
  return ['/page-1', '/parent/page-2']
}

预渲染所有页面

要拥有与 nuxt generate 相同的行为,同时保持服务器部分,您可以通过配置 nuxt.config.ts 中的 nitro.prerender 选项来预渲染所有页面。

nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    prerender: {
      // Pre-render the homepage
      routes: ['/'],
      // Then crawl all the links on the page
      crawlLinks: true
    }
  }
})

运行 nuxt build 时,Nuxt 将预渲染所有页面并将 index.html 文件保存在 dist/ 目录中。

了解有关 Nuxt 预渲染的更多信息。

Cloudflare 100 路由限制

NuxtHub 将为 Cloudflare Pages 生成 dist/_routes.json,但它有 100 个排除路由(用于静态资产)的限制。

由于每个预渲染的页面都将添加到排除列表中,我们建议您在 nitro.cloudflare.pages.routes.exclude 选项中添加您已知的预渲染模式。

nuxt.config.ts
export default defineNuxtConfig({
  // ...
  nitro: {
    cloudflare: {
      pages: {
        routes: {
          exclude: [
            // we know that all docs and blog pages are pre-rendered
            '/docs/*',
            '/blog/*'
          ]
        }
      }
    }
  }
})

警告

如果您在应用程序中使用身份验证,例如 nuxt-auth-utils,您需要记住,身份验证状态在预渲染过程中将不可用。

例如,如果您有一个标题组件,它要么显示已登录的用户,要么显示登录按钮,您需要将逻辑包装在 <AuthState> 组件中,以便在页面被预渲染时显示占位符。

components/AppHeader.vue
<script setup lang="ts">
const { loggedIn, user } = useUserSession()

const links = [
  { label: 'Docs', to: '/docs' },
  { label: 'Blog', to: '/blog' }
]
</script>

<template>
  <UHeader title="ACME" :links="links">
    <template #right>
      <AuthState>
        <UButton v-if="loggedIn" to="/profile">{{ user.name }}</UButton>
        <UButton v-else to="/login">Login</UButton>
        <template #placeholder>
          <!-- Display loading state -->
          <UButton :loading="true" />
        </template>
      </AuthState>
  </template>
</template>