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: falsefallback: "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が必要

初回アクセス時に動的に生成

useRouter().isFallback による分岐が必要

blocking

アクセス時にサーバーでSSG化。完了するまで何も表示されない

SSRのような挙動。ローディング不要

初回アクセスがやや遅い可能性あり

blockingの設定にした場合、もし取得するデータ量が多いと表示までにタイムラグがある。
表示されるまで画面は真っ白な状態になってしまうため、その場合は「ローディング中です」などのローディングUIを準備すると良い💡

⭐️fallback:trueにしてローディングUIを作る場合

useRouterrouter.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は常に再実行されるとのこと⚡️
そのため、新たに記事を投稿すると即座に一覧ページに表示される。

しかし本番環境では、初回ビルド時に取得したデータしか表示されない。

状態

実行タイミング

新記事が表示されるか

本番(next build && next start

getStaticPropsはビルド時のみ1回

❌ 表示されない(revalidateなしなら)

開発環境(npm run dev

毎回getStaticPropsが走る

✅ 表示される

✅ ISR(Incremental Static Regeneration)の設定をしてSSG記事一覧が古くなるのを防ぐ

revalidate オプションを使うことで、一定時間ごとに静的HTMLを再生成可能にしてくれる。
設定した時間経過後、最初のアクセス時にバックグラウンドで再生成が走る。

return {
  props: {
    articles: data.contents,
  },
  revalidate: 60, // ← 60秒ごとに再生成OK
};

これで、ビルド後も定期的に「自動更新」されるようになった🎉