# gt-next: General Translation Next.js SDK: 静态站点生成 URL: https://generaltranslation.com/zh/docs/next/guides/ssg.mdx --- title: 静态站点生成 description: 在构建阶段预渲染国际化页面,以实现最佳性能 --- ## 概述 静态站点生成 (SSG) 会在构建时预渲染页面,生成无需服务端处理即可直接提供的静态 HTML 文件。 与国际化结合使用时,SSG 会为每个区域设置生成预渲染版本。 **设置 SSG 时,请注意以下任一问题:** * [Next.js 版本兼容性](#nextjs-version-compatibility) * [页面未静态生成](#pages-not-generating-statically) * [生产环境 运行时 错误:“DYNAMIC_SERVER_USAGE”](#production-runtime-error-dynamic_server_usage) * [“Export locale doesn't exist in target module”](#export-locale-doesnt-exist-in-target-module) * [元数据图片路由 (OG 图片) 在使用 `getLocale()` 时失败](#metadata-image-routes-og-images-fail-with-getlocale) *** ## セットアップ ### 设置要求 要在 GT 中启用 SSG,您需要: 1. **使用中间件路由的 App Router** - 请参阅[中间件指南](/docs/next/guides/middleware) 2. **自定义 `getLocale` 函数** - 用于在静态渲染期间检测区域设置 3. **禁用 `getRegion`** - 静态渲染期间不支持区域检测 4. **`generateStaticParams` 函数** - 用于为每个区域设置生成静态参数 5. **位于 `/[locale]` 目录下的布局文件** - 所有布局文件 (通常是 `layout.tsx` 和 `page.tsx`) 都应位于 `/[locale]` 目录下 ### 第 1 步:配置中间件 为动态请求配置中间件 (请参阅[中间件指南](/docs/next/guides/middleware)) : ```ts // proxy.ts(Next.js 16+)或 middleware.ts(Next.js 15 及以下版本) import { createNextMiddleware } from 'gt-next/middleware'; export default createNextMiddleware(); export const config = { matcher: ['/((?!api|static|.*\\..*|_next).*)'], }; ``` ### 第 2 步:定义区域设置与区域检测 创建 `getLocale` 和 `getRegion` 函数,用于在静态渲染期间检测区域设置和区域: #### Next.js 15.5+ ```ts // getLocale.ts import { locale } from 'next/root-params'; export default async function getLocale() { return await locale(); } ``` #### Next.js 15.1-15.4 ```ts // getLocale.ts import { unstable_rootParams } from 'next/server'; export default async function getLocale() { return (await unstable_rootParams())?.locale; } ``` ### 步骤 3:禁用 getRegion 由于静态渲染不支持区域检测,你需要重写 `getRegion` 函数,让它返回一个固定的区域。 ```ts // getRegion.ts export default async function getRegion() { return undefined; } ``` ### 第 4 步:配置 generateStaticParams 确保你已为 locales 正确配置 [`generateStaticParams`](https://nextjs.org/docs/app/api-reference/functions/generate-static-params)。 ```tsx title="page.tsx" import { getLocales } from 'gt-next/server'; export async function generateStaticParams() { return getLocales().map((locale) => ({ locale })); } export default async function Page() { ... } ``` ### 第 5 步:将所有布局文件移到 `/[locale]` 目录下 所有文件都需要通过 URL 中的 `/[locale]` 字段获取用户的区域设置。 因此,它们都必须位于 `/[locale]` 目录下。 请确保将根布局文件移到 `/[locale]/layout.tsx`。 *** ## 其他设置 如果你不想将 `getLocale.ts` 和 `getRegion.ts` 放在根目录下,可以在 `next.config.js` 文件中指定自定义目录。 ```js // next.config.js export default withGTConfig(nextConfig, { getLocalePath: './src/i18n/getLocale.ts', getRegionPath: './src/i18n/getRegion.ts', }); ``` ## 常见问题 [#common-issues] ### Next.js 版本兼容性 对于低于 Next.js 15.1 的版本,静态生成期间无法访问 URL 路径参数。你需要升级到 Next.js 15.1 或更高版本,才能在 gt-next 中使用 SSG。 ### 页面未进行静态生成 如果你的页面未进行静态生成,请确保: * 你的 `getLocale` 和 `getRegion` 函数已正确配置 ### 生产环境运行时错误:"DYNAMIC_SERVER_USAGE" ``` ⨯ [Error: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.] { digest: 'DYNAMIC_SERVER_USAGE' } ``` 当 `getLocale` 或 `getRegion` 文件不存在,或配置不正确时,就会出现此错误。 请再次确认[步骤 2](#step-2-define-locale-and-region-detection)和[步骤 3](#step-3-disable-getregion)已完成。 ### "目标模块中不存在导出的区域设置" ``` ./getLocale.ts:2:1 Export locale doesn't exist in target module 1 | // getLocale.ts > 2 | import { locale } from 'next/root-params'; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 3 | export default async function getLocale() { 4 | return await locale(); 5 | } ``` 此错误通常发生在项目中存在 `layout.tsx`、`page.tsx` 等文件,但它们不在 `/[locale]` 目录内时。 要修复此问题,请确保所有路由段文件 (通常是 `layout.tsx` 和 `page.tsx`) 都位于 `/[locale]` 目录下。 在 SSG 期间,解析用户区域设置的唯一方式是通过 URL 路径。 因此,如果我们尝试执行位于 `/[locale]` 目录之外的 `layout.tsx` 文件,就会报错,因为它无法访问这个根参数。 这里不太直观的一点在于:页面渲染时,所有包裹该页面的 `layout.tsx` 文件也都会一起渲染。 所以,你可能为一个明确位于 `/[locale]` 目录内的 `page.tsx` 文件启用了 SSG,但实际导致报错的却是别处的某个 `layout.tsx` 文件。 我们强烈不建议这样做。 使用 SSG 时,所有路由段文件 (`not-found.tsx` 除外) 都应放在 `/[locale]` 目录内。 不过,如果你确实必须这样做,就需要两个独立的根布局文件:一个位于 `/[locale]` 目录内,另一个位于其外部。 这样,SSG 只会执行 `/[locale]` 目录内的布局。 此外,你可能还需要修改中间件,使其将路由转发到 `/[locale]` 目录之外的那些段,并跳过本地化中间件。 ### 元数据图片路由 (OG 图片) 无法与 `getLocale()` 配合使用 ``` Error: Route /[locale]/.../opengraph-image used import('next/root-params').locale() inside a Route Handler. ``` Next.js 元数据图片路由 (`opengraph-image.tsx`、`twitter-image.tsx`) 在内部实际上是 Route Handler,而 `next/root-params` 不支持在 Route Handler 中使用。 这意味着 `getLocale()`、`getMessages()` 和 `getGT()` 在这些场景下都会失效。 **修复方法:** 在 handler 顶部使用 `registerLocale()` 显式设置区域设置: ```tsx title="app/[locale]/opengraph-image.tsx" import { ImageResponse } from 'next/og'; import { registerLocale, getMessages, msg } from 'gt-next/server'; const HEADING = msg('Welcome to our site'); export default async function OGImage({ params, }: { params: Promise<{ locale: string }>; }) { const { locale } = await params; registerLocale(locale); const m = await getMessages(); return new ImageResponse( (
{m(HEADING)}
), { width: 1200, height: 630 } ); } ``` 这同样适用于 `twitter-image.tsx` 和其他任何元数据图片路由。 *** ## 延伸阅读 **查看实际效果:** 查看[静态站点生成示例应用](https://github.com/gt-examples/static-site-generation)以获取可运行的演示——[在线预览](https://static-site-generation.generaltranslation.dev)。 * 查看区域设置路由所需的[中间件指南](/docs/next/guides/middleware) * 查看有关从旧版 SSG 模式迁移的[发布说明](/devlog/gt-next_v6_10_0) * 在 monorepo 中[这里](https://github.com/generaltranslation/gt/tree/main/examples/next-ssg)查看示例应用