Skip to content

generateViewport

你可以使用静态 viewport 对象或动态 generateViewport 函数自定义页面的初始视口。

¥You can customize the initial viewport of the page with the static viewport object or the dynamic generateViewport function.

需要了解:

¥Good to know:

  • 仅服务器组件支持 viewport 对象和 generateViewport 函数导出。

    ¥The viewport object and generateViewport function exports are only supported in Server Components.

  • 你不能从同一线路段同时导出 viewport 对象和 generateViewport 功能。

    ¥You cannot export both the viewport object and generateViewport function from the same route segment.

  • 如果你刚刚迁移 metadata 导出,则可以使用 元数据到视口导出 codemod 来更新你的更改。

    ¥If you're coming from migrating metadata exports, you can use metadata-to-viewport-export codemod to update your changes.

viewport 对象

¥The viewport object

要定义视口选项,请从 layout.jsxpage.jsx 文件导出 viewport 对象。

¥To define the viewport options, export a viewport object from a layout.jsx or page.jsx file.

tsx
import type { Viewport } from 'next'

export const viewport: Viewport = {
  themeColor: 'black',
}

export default function Page() {}

generateViewport 功能

¥generateViewport function

generateViewport 应返回包含一个或多个视口字段的 Viewport 对象

¥generateViewport should return a Viewport object containing one or more viewport fields.

tsx
export function generateViewport({ params }) {
  return {
    themeColor: '...',
  }
}

在 TypeScript 中,params 参数可以通过 PageProps<'/route'>LayoutProps<'/route'> 进行类型化,具体取决于 generateViewport 的定义位置。

¥In TypeScript, the params argument can be typed via PageProps<'/route'> or LayoutProps<'/route'> depending on where generateViewport is defined.

需要了解:

¥Good to know:

  • 如果视口不依赖于运行时信息,则应使用静态 viewport 对象 而不是 generateViewport 来定义它。

    ¥If the viewport doesn't depend on runtime information, it should be defined using the static viewport object rather than generateViewport.

视口字段

¥Viewport Fields

themeColor

了解有关 theme-color 的更多信息。

¥Learn more about theme-color.

简单主题颜色

¥Simple theme color

tsx
import type { Viewport } from 'next'

export const viewport: Viewport = {
  themeColor: 'black',
}
html
<meta name="theme-color" content="black" />

使用 media 属性

¥With media attribute

tsx
import type { Viewport } from 'next'

export const viewport: Viewport = {
  themeColor: [
    { media: '(prefers-color-scheme: light)', color: 'cyan' },
    { media: '(prefers-color-scheme: dark)', color: 'black' },
  ],
}
html
<meta name="theme-color" media="(prefers-color-scheme: light)" content="cyan" />
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="black" />

widthinitialScalemaximumScaleuserScalable

¥width, initialScale, maximumScale and userScalable

需要了解:viewport 元标记是自动设置的,通常不需要手动配置,因为默认值就足够了。然而,提供该信息是为了完整性。

¥Good to know: The viewport meta tag is automatically set, and manual configuration is usually unnecessary as the default is sufficient. However, the information is provided for completeness.

tsx
import type { Viewport } from 'next'

export const viewport: Viewport = {
  width: 'device-width',
  initialScale: 1,
  maximumScale: 1,
  userScalable: false,
  // Also supported but less commonly used
  // interactiveWidget: 'resizes-visual',
}
html
<meta
  name="viewport"
  content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
/>

colorScheme

了解有关 color-scheme 的更多信息。

¥Learn more about color-scheme.

tsx
import type { Viewport } from 'next'

export const viewport: Viewport = {
  colorScheme: 'dark',
}
html
<meta name="color-scheme" content="dark" />

使用缓存组件

¥With Cache Components

启用 缓存组件 后,generateViewport 遵循与其他组件相同的规则。如果 viewport 访问运行时数据(cookies()headers()paramssearchParams)或执行未缓存的数据获取,则会延迟到请求时执行。

¥When Cache Components is enabled, generateViewport follows the same rules as other components. If viewport accesses runtime data (cookies(), headers(), params, searchParams) or performs uncached data fetching, it defers to request time.

与元数据不同,视口数据不能流式传输,因为它会影响初始页面加载 UI。如果 generateViewport 延迟到请求时间,则页面需要阻塞直到解析完成。

¥Unlike metadata, viewport cannot be streamed because it affects initial page load UI. If generateViewport defers to request time, the page would need to block until resolved.

如果 viewport 依赖外部数据但不依赖运行时数据,请使用 use cache

¥If viewport depends on external data but not runtime data, use use cache:

tsx
export async function generateViewport() {
  'use cache'
  const { width, initialScale } = await db.query('viewport-size')
  return { width, initialScale }
}

如果 viewport 确实需要运行时数据,请将文档的 <body> 封装在 Suspense 边界中,以表明整个路由应该是动态的:

¥If viewport genuinely requires runtime data, wrap the document <body> in a Suspense boundary to signal that the entire route should be dynamic:

tsx
import { Suspense } from 'react'
import { cookies } from 'next/headers'

export async function generateViewport() {
  const cookieJar = await cookies()
  return {
    themeColor: cookieJar.get('theme-color')?.value,
  }
}

export default function RootLayout({ children }) {
  return (
    <Suspense>
      <html>
        <body>{children}</body>
      </html>
    </Suspense>
  )
}

缓存是首选方案,因为它允许静态 shell 生成。将文档 body 封装在 Suspense 中意味着当请求到达时,没有静态 shell 或内容可以立即发送,因此每个请求都会阻塞整个路由,直到准备就绪。

¥Caching is preferred because it allows static shell generation. Wrapping the document body in Suspense means there is no static shell or content to immediately send when a request arrives, making the entire route block until ready on every request.

需要了解:使用 多个根布局 将完全动态的视口隔离到特定路由,同时仍然允许应用中的其他路由生成静态 shell。

¥Good to know: Use multiple root layouts to isolate fully dynamic viewport to specific routes, while still letting other routes in your application generate a static shell.

类型

¥Types

你可以使用 Viewport 类型向视口对象添加类型安全性。如果你在 IDE 中使用 内置 TypeScript 插件,则无需手动添加类型,但如果需要,你仍然可以显式添加它。

¥You can add type safety to your viewport object by using the Viewport type. If you are using the built-in TypeScript plugin in your IDE, you do not need to manually add the type, but you can still explicitly add it if you want.

viewport 对象

¥viewport object

tsx
import type { Viewport } from 'next'

export const viewport: Viewport = {
  themeColor: 'black',
}

generateViewport 功能

¥generateViewport function

常规功能

¥Regular function

tsx
import type { Viewport } from 'next'

export function generateViewport(): Viewport {
  return {
    themeColor: 'black',
  }
}

带分段属性

¥With segment props

tsx
import type { Viewport } from 'next'

type Props = {
  params: Promise<{ id: string }>
  searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}

export function generateViewport({ params, searchParams }: Props): Viewport {
  return {
    themeColor: 'black',
  }
}

export default function Page({ params, searchParams }: Props) {}

JavaScript 项目

¥JavaScript Projects

对于 JavaScript 项目,你可以使用 JSDoc 添加类型安全。

¥For JavaScript projects, you can use JSDoc to add type safety.

版本历史

¥Version History

版本更改
v14.0.0引入了 viewportgenerateViewport