# 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)查看示例应用