Next.js × microCMS|SSGで記事を10件のみ生成。ユーザーアクションで取得した11件目へのアクセスは404になる原因と解決方法
CSRで新しく取得した記事が404になる原因とその解決方法。fallbackの設定で解決!
4/11/2025
⚡️新しく取得した記事にアクセスしたら404エラーに
ブログ記事一覧ページに無限スクロールを設置。
最初のアクセス時、10件分はSSGで静的HTMLを生成して表示して、11件目以降はユーザーのスクロールで取得する機能を実装。
しかし、11件目以降の記事にアクセスすると404が表示された。
✅原因はfallbackの設定
getStaticPathsの設定でfallback: falseにしていたことが原因。
ビルド時getStaticPathsで取得したデータに存在しなかったページは作られず、アクセスしても404になるとのこと。
export const getStaticPaths = async () => {
const data = await getBlogDetail();
const paths = data.contents.map((content) => `/blogs/${content.id}`);
return { paths, fallback: false};
};ビルド後に動的ページにアクセスしたいならfallbackの設定が重要。
fallbackは、まだ生成されていないページにアクセスされたときの挙動を決めるオプション。
fallbackの設定を変えて解決🎉
fallback: false→fallback: "blocking"に変更すると初回アクセスでも表示された。
🔵blockingの挙動
ユーザーがアクセスするとサーバーがアクセスしたページをSSG化してくれる。
SSG化している間画面には何も表示されず、完了しだい該当ページが表示される。
export const getStaticPaths = async () => {
const data = await getBlogDetail();
const paths = data.contents.map((content) => `/blogs/${content.id}`);
return { paths, fallback: "blocking" };
};🔁fallback の3つの設定
fallbackには下記3つの設定があり、それぞれの挙動が異なる。
設定 | 挙動 | 特徴 | 注意点 |
|---|---|---|---|
false | ビルド時に定義されたパスのみSSG化。存在しないページは404 | 最もシンプル | ページ追加時に再ビルドが必要。 |
true | ユーザーがアクセスした時に初めてSSG化。ローディングUIが必要 | 初回アクセス時に動的に生成 |
|
blocking | アクセス時にサーバーでSSG化。完了するまで何も表示されない | SSRのような挙動。ローディング不要 | 初回アクセスがやや遅い可能性あり |
blockingの設定にした場合、もし取得するデータ量が多いと表示までにタイムラグがある。
表示されるまで画面は真っ白な状態になってしまうため、その場合は「ローディング中です」などのローディングUIを準備すると良い💡
⭐️fallback:trueにしてローディングUIを作る場合
useRouter の router.isFallback を使ってローディングUIを表示させる。
fallback: true のときは、まだ静的に生成されていないページにアクセスされると、最初はpropsが渡ってこない状態でページが表示され始める。
その間は router.isFallback が true になるので、それを使って「ローディング中」のUIを表示させる仕組み。
const CommentID = (props) => {
const { fallback } = props;
const router = useRouter();
if (router.isFallback) {
return <div>ローディング中</div>;
}⚠️Static Generationのfallbackは開発環境と本番環境で挙動が異なる
開発環境 (npm run dev) では、getStaticPropsは常に再実行されるとのこと⚡️
そのため、新たに記事を投稿すると即座に一覧ページに表示される。
しかし本番環境では、初回ビルド時に取得したデータしか表示されない。
状態 | 実行タイミング | 新記事が表示されるか |
|---|---|---|
本番( | getStaticPropsはビルド時のみ1回 | ❌ 表示されない(revalidateなしなら) |
開発環境( | 毎回getStaticPropsが走る | ✅ 表示される |
✅ ISR(Incremental Static Regeneration)の設定をしてSSG記事一覧が古くなるのを防ぐ
revalidate オプションを使うことで、一定時間ごとに静的HTMLを再生成可能にしてくれる。
設定した時間経過後、最初のアクセス時にバックグラウンドで再生成が走る。
return {
props: {
articles: data.contents,
},
revalidate: 60, // ← 60秒ごとに再生成OK
};これで、ビルド後も定期的に「自動更新」されるようになった🎉