
Next.js静的生成(SSG)の基本
2025-08-13はじめに
Next.jsの大きな特徴である「静的生成(Static Site Generation: SSG)」について、初心者の方にもわかりやすく解説します。SSGを理解することで、高速でSEOに強く、安全なWebサイトを構築できるようになります。
静的生成(SSG)とは?
静的生成とは、ビルド時にHTMLファイルを事前に生成する手法です。ユーザーがページにアクセスする前に、あらかじめページが準備されているため、以下のようなメリットがあります:
- 超高速なページ表示
- サーバー負荷が軽減
- SEOに有利
- CDNでの配信が容易
- 高いセキュリティ(サーバーサイドコードが不要)
SSGの基本的な仕組み
ビルド時(npm run build)
↓
データ取得(getStaticProps)
↓
HTML生成
↓
ユーザーアクセス時に生成済みHTMLを配信
基本的なSSGの実装方法
1. データを必要としない静的ページ
最もシンプルなSSGページは、通常のReactコンポーネントと同じ書き方で実現できます。
// pages/about.js
function About() {
return (
<div>
<h1>About Us</h1>
<p>私たちの会社についての情報ページです</p>
</div>
);
}
export default About;
このページはビルド時に静的なHTMLとして生成されます。
2. 外部データを使用する静的ページ
外部データ(APIやデータベースなど)を使用する場合、getStaticProps
関数を追加します。
// pages/blog.js
function Blog({ posts }) {
return (
<div>
<h1>ブログ記事一覧</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
// ビルド時にデータを取得
export async function getStaticProps() {
// 実際のアプリではAPIやデータベースからデータを取得
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
return {
props: {
posts,
},
};
}
export default Blog;
getStaticPropsの詳細
getStaticProps
はNext.jsが提供する特別な関数で、以下の特徴があります:
- ビルド時に実行される
- サーバーサイドで実行される(クライアントバンドルに含まれない)
- ページコンポーネントにpropsを渡せる
返却値のオプション
export async function getStaticProps() {
// データ取得処理...
return {
props: {}, // ページコンポーネントに渡すprops
revalidate: 10, // ISR(後述)を使用する場合の再生成間隔(秒)
notFound: false, // 404ページを表示するか
redirect: { // リダイレクトする場合
destination: '/other-page',
permanent: false,
},
};
}
動的ルートの静的生成
動的ルート(例:[id].js
)を使用する場合、getStaticPaths
も併せて使用します。
基本的な実装例
// pages/posts/[id].js
function Post({ post }) {
return (
<div>
<h1>{post.title}</h1>
<p>{post.content}</p>
</div>
);
}
// ビルド時に生成するパスを指定
export async function getStaticPaths() {
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
// プリレンダリングするパスを指定
const paths = posts.map((post) => ({
params: { id: post.id.toString() },
}));
return {
paths,
fallback: false, // 後述
};
}
// 各パスに対してデータを取得
export async function getStaticProps({ params }) {
const res = await fetch(`https://api.example.com/posts/${params.id}`);
const post = await res.json();
return {
props: {
post,
},
};
}
export default Post;
fallbackの3つのモード
getStaticPaths
のfallback
オプションには重要な3つの設定があります:
1. fallback: false
- ビルド時に生成されていないパスは404ページになる
- 全てのパスをビルド時に生成する場合に使用
2. fallback: true
- ビルド時に生成されていないパスにアクセスすると、バックグラウンドでHTMLを生成
- 初回アクセス時はローディング状態を表示する必要がある
function Post({ post }) {
const router = useRouter();
// 初回ロード中の表示
if (router.isFallback) {
return <div>Loading...</div>;
}
// 通常の表示
return (
<div>
<h1>{post.title}</h1>
<p>{post.content}</p>
</div>
);
}
3. fallback: 'blocking'
- ビルド時に生成されていないパスに初めてアクセスした時にサーバーサイドでHTMLを生成
- 生成が完了するまでユーザーは待機状態(ローディング表示不要)
インクリメンタル静的再生(ISR)
Next.js 9.5で導入されたISR(Incremental Static Regeneration)を使うと、ビルド後も定期的にページを再生成できます。
export async function getStaticProps() {
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
return {
props: {
posts,
},
// 10秒ごとにページを再生成
revalidate: 10,
};
}
ISRの動作フロー:
- 初回アクセス:事前生成されたHTMLを表示
- 10秒後のアクセス:キャッシュされたHTMLを表示
- 10秒経過後の最初のアクセス:バックグラウンドで再生成
- 再生成完了後:新しいHTMLを表示
SSGの使用が適しているケース
- ブログやニュースサイト
- 製品紹介ページ
- ドキュメンテーション
- マーケティングページ
- 更新頻度が低いコンテンツ
SSGのベストプラクティス
1. データ取得の最適化
// 悪い例(複数のAPI呼び出しが並列化されていない)
export async function getStaticProps() {
const user = await fetchUser();
const posts = await fetchPosts();
return { props: { user, posts } };
}
// 良い例(Promise.allで並列処理)
export async function getStaticProps() {
const [user, posts] = await Promise.all([
fetchUser(),
fetchPosts(),
]);
return { props: { user, posts } };
}
2. エラーハンドリング
export async function getStaticProps() {
try {
const res = await fetch('https://api.example.com/data');
if (!res.ok) {
throw new Error('データの取得に失敗しました');
}
const data = await res.json();
return {
props: {
data,
},
};
} catch (error) {
console.error(error);
return {
notFound: true, // 404ページを表示
// またはエラーメッセージをpropsとして渡す
// props: { error: error.message },
};
}
}
3. 環境変数の使用
APIエンドポイントや認証情報は環境変数で管理:
export async function getStaticProps() {
const res = await fetch(process.env.API_URL);
// ...
}
実際のプロジェクトでの使用例
ブログ記事一覧と詳細ページ
// pages/index.js
export default function Home({ recentPosts }) {
return (
<div>
<h1>最新記事</h1>
{recentPosts.map((post) => (
<Link key={post.id} href={`/posts/${post.id}`}>
<a>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</a>
</Link>
))}
</div>
);
}
export async function getStaticProps() {
const res = await fetch('https://api.example.com/posts?_limit=5');
const recentPosts = await res.json();
return {
props: {
recentPosts,
},
revalidate: 60, // 60秒ごとに再生成
};
}
export default function Post({ post }) {
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
);
}
export async function getStaticPaths() {
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
const paths = posts.map((post) => ({
params: { id: post.id.toString() },
}));
return {
paths,
fallback: 'blocking',
};
}
export async function getStaticProps({ params }) {
const res = await fetch(`https://api.example.com/posts/${params.id}`);
if (!res.ok) {
return {
notFound: true,
};
}
const post = await res.json();
return {
props: {
post,
},
revalidate: 3600, // 1時間ごとに再生成
};
}
まとめ
Next.jsの静的生成(SSG)について学びました。主なポイントは:
- SSGはビルド時にHTMLを生成するため、高速で安全
getStaticProps
でビルド時にデータを取得- 動的ルートには
getStaticPaths
を使用 fallback
オプションで柔軟なページ生成が可能- ISR(インクリメンタル静的再生)で定期的な再生成が可能
SSGはパフォーマンスと開発体験の両方を向上させる強力な機能です。ただし、ユーザーごとに内容が変わるページや、リアルタイム性が求められるページには不向きです。そのようなケースでは、次回解説する「サーバーサイドレンダリング(SSR)」が適しています。
Next.jsの公式ドキュメントも参考にしてください:
https://nextjs.org/docs/basic-features/data-fetching/get-static-props