Next.jsのレンダリング
Next.js を学ぶ上で少し難しく、しかし最も重要なのが 「レンダリング(HTMLの生成)」 の仕組みです。
「いつ」「どこで」HTMLが作られるのかを理解すると、Next.js で作れるアプリケーションの幅がぐっと広がります。
レンダリングとは?
React や Next.js におけるレンダリングとは、 コードを元にブラウザが表示できるHTMLを組み立てること を指します。
この「組み立て」を、
- サーバー でやるのか? ブラウザ (クライアント)でやるのか?
- ビルド時 に1回だけやるのか? アクセスがある度 に毎回やるのか?
これらを使い分けるのが Next.js の強力な機能です。
主なレンダリング方式
1. Static Site Generation (SSG) / 静的サイト生成
- タイミング : ビルド時(
npm run buildをした時) - 場所 : サーバー(ビルド環境)
- 特徴 : あらかじめHTMLファイルを作っておくので、アクセス時の表示が 爆速 です。ブログ記事やドキュメントなど、内容が頻繁に変わらないページに向いています。
2. Server-Side Rendering (SSR) / サーバーサイドレンダリング
- タイミング : リクエスト時(ユーザーがアクセスした瞬間)
- 場所 : サーバー
- 特徴 : アクセスのたびに最新データでHTMLを作ります。SNSのタイムラインやダッシュボードなど、常に最新情報が必要なページに向いています。
3. Client-Side Rendering (CSR)
- タイミング : ブラウザでJavaScriptが実行された時
- 場所 : ブラウザ(クライアント)
- 特徴 : サーバーからは最低限のHTMLだけを送り、ブラウザ側でJavaScriptが画面を組み立てます。ユーザー操作に応じて画面が変わるアプリケーションのような動き(検索画面やフィルター機能など)に向いています。
- ※ Next.js では、初期表示はサーバーで作るのが基本ですが、
use clientを使うことでブラウザ側での動的な振る舞いを追加できます。
Next.js (App Router) での使い分け
App Router では、 fetch関数 の書き方ひとつで、SSGやSSRを切り替えることができます。
⚠️ 重要: 最新仕様での変更点
近年、fetch 関数のデフォルト挙動が変更されました。 「デフォルトではキャッシュされない(=毎回最新を取得するSSR的な挙動)」 になっています。
以前の仕様ではデフォルトがキャッシュ(SSG)でしたが、これが逆転しました。より直感的なWeb標準の挙動(GETリクエストは最新を取得する)に合わせた変更です。
実装パターンの例
データ取得のコード例を見てみましょう。
パターンA: 毎回最新を取得する (SSR)
デフォルトの挙動です。アクセスするたびにAPIを叩いて最新データを表示します。
// 特別なオプションは不要(最新仕様) const res = await fetch("https://api.example.com/data");
パターンB: ビルド時に取得してキャッシュする (SSG)
ブログ記事のように、ビルド時に一度だけ取得すれば良い場合は force-cache を指定します。
// キャッシュを強制する(SSGとして動作) const res = await fetch("https://api.example.com/posts", { cache: "force-cache", });
パターンC: 一定時間ごとに更新する (ISR)
「基本はキャッシュしたいけど、1時間おきに更新したい」といった場合は revalidate オプションを使います。これを ISR (Incremental Static Regeneration) と呼びます。
// 3600秒(1時間)ごとにデータを更新 const res = await fetch("https://api.example.com/news", { next: { revalidate: 3600 }, });
サーバーコンポーネントとクライアントコンポーネント
Next.js App Router にはもう一つ重要な概念があります。
Server Components (デフォルト)
Next.js のコンポーネントは、デフォルトでは サーバーコンポーネント として扱われます。
これらはサーバー側でのみ実行され、結果のHTMLだけがブラウザに届きます。
- ✅ データベースへの直接アクセスが可能
- ✅ APIキーなどの秘密情報を隠せる
- ✅ JavaScriptコードがブラウザに送られないので高速
Client Components ("use client")
ボタンのクリックイベント(onClick)や、フック(useState, useEffect)を使いたい場合は、ファイルの先頭に "use client" と宣言します。
これにより、そのコンポーネントはブラウザ側でJavaScriptとして動作するようになります。
sample.tsx"use client"; // これを書くとクライアントコンポーネントになる import { useState } from "react"; export default function Counter() { const [count, setCount] = useState(0); // フックが使える return <button onClick={() => setCount(count + 1)}>{count}</button>; }
** 使い分けのコツ** :
基本はサーバーコンポーネントで作り、ユーザーが操作する部分(ボタン、フォームなど)だけを小さなクライアントコンポーネントとして切り出すのが「Next.js流」の設計です。
まとめ
- SSG : ビルド時に作る(速い・キャッシュ) ->
cache: 'force-cache' - SSR : アクセスのたびに作る(最新) ->
fetchのデフォルト - ISR : 定期的に作り直す ->
revalidate - Component : 基本はサーバー側。操作が必要なら
"use client"。
少し複雑に見えるかもしれませんが、コードを書きながら「ここはキャッシュしたいな」「ここは最新がいいな」と意識することで自然と身についていきます。
次章では、設定ファイルや環境変数について触れていきます。
更新履歴
- 2025-01-04 : ページのレイアウト崩れ・誤字を修正しました。