# gt-next: General Translation Next.js SDK: 静的サイト生成 URL: https://generaltranslation.com/ja/docs/next/guides/ssg.mdx --- title: 静的サイト生成 description: 最適なパフォーマンスを実現するため、ビルド時に多言語対応ページを事前レンダリングします --- ## 概要 静的サイト生成 (SSG) は、ビルド時にページを事前レンダリングし、サーバー側での処理なしに直接配信できる静的なHTMLファイルを生成します。 国際化と組み合わせると、SSG は各ロケール向けの事前レンダリング済みページを生成します。 **SSG を設定する際は、次の問題に注意してください。** * [Next.js のバージョン互換性](#nextjs-version-compatibility) * [ページが静的に生成されない](#pages-not-generating-statically) * [本番環境での runtime エラー: "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** - [middleware guide](/docs/next/guides/middleware)を参照してください 2. **カスタム `getLocale` 関数** - 静的レンダリング時のロケール検出に使用します 3. **`getRegion` の無効化** - 静的レンダリングではリージョン検出はサポートされていません 4. **`generateStaticParams` 関数** - 各ロケールの静的パラメータを生成するために使用します 5. **`/[locale]` ディレクトリ内のレイアウトファイル** - すべてのレイアウトファイル (通常は `layout.tsx` と `page.tsx`) を `/[locale]` ディレクトリ配下に配置する必要があります ### ステップ 1: ミドルウェアを設定する 動的リクエスト向けにミドルウェアを設定します ([middleware guide](/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 を設定する 各ロケールに対して [`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 のパスパラメータへアクセスすることはできません。gt-next で SSG を使うには、Next.js 15.1 以降にアップグレードする必要があります。 ### ページが静的生成されない ページが静的に生成されない場合は、次の点を確認してください。 * `getLocale` と `getRegion` 関数が正しく設定されていること ### 本番環境での runtime エラー: "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 | } ``` このエラーは通常、`/[locale]` ディレクトリ内にない `layout.tsx`、`page.tsx` などのファイルがある場合に発生します。 この問題を解決するには、すべてのルートセグメントファイル (通常は `layout.tsx` と `page.tsx`) が `/[locale]` ディレクトリ配下にあることを確認してください。 SSG では、ユーザーのロケールを特定する唯一の方法は URL パスです。 そのため、`/[locale]` ディレクトリの外にある `layout.tsx` ファイルを実行しようとすると、このルートパラメータにアクセスできないためエラーになります。 わかりにくいのは、ページがレンダリングされると、それをラップしているすべての `layout.tsx` ファイルも一緒にレンダリングされる点です。 つまり、`/[locale]` ディレクトリ内にある `page.tsx` ファイルに SSG を追加していても、実際には別の場所にある `layout.tsx` ファイルがエラーの原因になっている可能性があります。 この構成は強く非推奨です。 SSG を使用する場合、すべてのルートセグメントファイル (`not-found.tsx` を除く) は `/[locale]` ディレクトリ内に配置する必要があります。 それでも必要な場合は、`/[locale]` ディレクトリ内と外に、それぞれ別個のルートレイアウトファイルを 1 つずつ用意する必要があります。 こうすることで、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 Handlers として扱われ、Route Handlers では `next/root-params` はサポートされていません。 そのため、`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)。 * ロケールルーティングに必要な [middleware ガイド](/docs/next/guides/middleware) を確認してください * レガシーな SSG パターンから移行する場合は、[リリースノート](/devlog/gt-next_v6_10_0) を確認してください * monorepo 内のサンプルアプリの例は [こちら](https://github.com/generaltranslation/gt/tree/main/examples/next-ssg) を参照してください