Next.jsのレンダリング方式:SSG(Static Site Generation)
Next.js v15.3.5時点でのApp RouterにおけるSSGについての学習メモです。
基本的な静的ページ
App Routerでは可能な限り静的なページとしてレンダリングされる。 例えばこのブログではトップとaboutページは静的なものという判断になる。
Route (app) Size First Load JS Revalidate Expire
┌ ○ / 175 B 104 kB 1h 1y
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
└ ○ /about 5.49 kB 110 kB
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
○ (Static) prerendered as static content
● (SSG) prerendered as static HTML (uses generateStaticParams)試しにaboutページに
export const dynamic = "force-dynamic";
を入れたところサーバーレンダリングとなった。
└ ƒ /about 5.49 kB 110 kB
ƒ (Dynamic) server-rendered on demandビルド時にHTMLとして生成されるため初期表示を最も早く実現することができる。 また、トップページにようにAPIから取得する場合でもキャッシュができており、リクエストヘッダーの情報を取得するよう動的な作りでは無い限り静的なページとしてレンダリングされる。
動的ルートでの静的ページ
動的なルート、例えば(/blogs/[id])のようなルートで静的サイトを生成する場合はgenerateStaticParams関数とdynamicParamsという設定を使用する。
dynamicParamsはRoute Segment Configと呼ばれるものの一つで、直接exportとして定義することでページの挙動を設定することができる。dynamicParamsはbooleanで、trueが設定されるとgenerateStaticParamsで事前生成されていないパスにアクセスがあった時、サーバー上でレンダリングし、その結果をキャッシュする。falseだとレンダリングはされず404となる。
デフォルトはtrueとなっている。
// /app/blogs/[id]
export const dynamicParams = true;
export async function generateStaticParams() {
const posts = await fetch('https://api.example.com/posts').then(res => res.json());
return posts.map((post: any) => ({
id: post.id.toString(), // ここで動的ページのIDパスに対応したプロパティでIDの一覧を返す
}));
}
export default async function PostPage({ params }: { params: { id: string } }) {
const post = await fetch(`https://api.example.com/posts/${params.id}`)
.then(res => res.json());
return (
<div>
<h1>{post.title}</h1>
<p>{post.content}</p>
</div>
);
}記事データを取得するような静的ページでは生成時に何らかの原因でデータが取得できずエラーで生成するとそれがキャッシュされてしまう。なのでエラー時はキャッシュしない・revalidateを設定するなどといった考慮をする必要がある。
Tips💡 : generateStaticParamsを設定しないとbuild時に生成されず、アクセスがある度生成されキャッシュされるようになる。さらにその状態でdynamicParamsがfalseだと全て404になる。
サイト全体の静的サイト化
next.config.jsにoutput: 'export'を設定することで静的ファイルとして出力することができる。これにより、AWS S3などに配置することでホスティングが可能になる。
また、サーバー上で動作させる必要のあるものなどは使用することができない。
How to create a static export of your Next.js application
next.config.jsで次のような設定を行い、next buildを実行するとout/が作成されるのでそれを配置すればよい。
// next.config.js
const nextConfig = {
output: 'export'
}