Next.js 14のApp Routerでは、レンダリング方式の選択が柔軟になりました。SSR(サーバーサイドレンダリング)、SSG(静的サイト生成)、ISR(増分静的再生成)をページ単位・コンポーネント単位で使い分ける方法を解説します。
App Routerの基本
Next.js 13以降のApp Routerでは、デフォルトですべてのコンポーネントがServer Componentになります。これにより、クライアントに送信されるJavaScriptの量が大幅に削減されます。
// app/page.tsx - デフォルトでServer Component
export default async function HomePage() {
// サーバー側で実行される
const data = await fetch("https://api.example.com/posts");
const posts = await data.json();
return (
<main>
<h1>最新記事</h1>
{posts.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</article>
))}
</main>
);
}
SSG(静的生成)
ビルド時にHTMLを生成する方式です。ブログ記事やドキュメントなど、更新頻度が低いコンテンツに最適です。
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await fetch("https://api.example.com/posts").then(r => r.json());
return posts.map(post => ({ slug: post.slug }));
}
export default async function BlogPost({ params }) {
const post = await fetch(
`https://api.example.com/posts/${params.slug}`,
{ cache: "force-cache" } // SSG: ビルド時にキャッシュ
).then(r => r.json());
return <article><h1>{post.title}</h1><div>{post.content}</div></article>;
}
SSR(サーバーサイドレンダリング)
リクエストごとにサーバーでHTMLを生成します。ユーザーごとに異なるコンテンツを表示する場合に使います。
// app/dashboard/page.tsx
export default async function Dashboard() {
const data = await fetch("https://api.example.com/user/dashboard", {
cache: "no-store", // SSR: キャッシュしない
headers: { Authorization: `Bearer ${getToken()}` }
}).then(r => r.json());
return <div>ようこそ、{data.user.name}さん</div>;
}
ISR(増分静的再生成)
SSGとSSRの良いとこ取り。静的に生成されたページを一定時間後にバックグラウンドで再生成します。
// app/products/page.tsx
export default async function Products() {
const products = await fetch("https://api.example.com/products", {
next: { revalidate: 3600 } // ISR: 1時間ごとに再生成
}).then(r => r.json());
return (
<div>
{products.map(p => <div key={p.id}>{p.name} - ¥{p.price}</div>)}
</div>
);
}
使い分けの判断基準
どのレンダリング方式を使うかは、コンテンツの特性で決めます。更新頻度が低い(ブログ・ドキュメント)→ SSG、リアルタイム性が必要(ダッシュボード)→ SSR、適度に更新される(商品一覧・ニュース)→ ISR、が基本的な選び方です。
まとめ
App Routerでは、fetchのオプションを変えるだけでレンダリング方式を切り替えられます。ページの特性に合わせて最適な方式を選ぶことで、パフォーマンスとユーザー体験を両立できます。
コメントを残す