Next.jsのgetStaticPathsでフィルタリングが失敗する原因と解決方法

公開日:
目次

Next.jsでブログサイトを作っていて、タグページの2ページ目以降が404エラーになる問題に遭遇しました。原因はgetStaticPathsでのフィールド取得不備でした。同じ問題で悩んでいる方向けに、解決方法をシンプルに解説します。

発生した問題

ブログサイトで以下のような構造を作っていました:

/tags/javascript      ← 1ページ目(正常)
/tags/javascript/2    ← 2ページ目(404エラー)
/tags/react          ← 1ページ目(正常)
/tags/react/2        ← 2ページ目(404エラー)

1ページ目は正常に表示されるのに、2ページ目以降で404エラーが発生していました。

原因の調査

デバッグログを追加して確認したところ、getStaticPathsで全てのタグがPosts: 0になっていました:

Tag: javascript, Posts: 0, Pages: 0
Tag: react, Posts: 0, Pages: 0
Tag: nextjs, Posts: 0, Pages: 0

明らかに記事は存在するのに、なぜ0件になってしまうのでしょうか?

問題の根本原因

原因はgetStaticPaths内のgetTagPosts呼び出しでした:

// 問題のあるコード
export const getStaticPaths: GetStaticPaths = async () => {
  const tags = getAllTags()
  const paths = []
  
  for (const tag of tags) {
    // ここが問題:'slug'しか取得していない
    const tagPosts = getTagPosts(tag, ['slug'])
    const totalPages = Math.ceil(tagPosts.length / POSTS_PER_PAGE)
    
    // tagPosts.lengthが常に0になる
  }
}

getTagPostsの内部では、記事をtagフィールドでフィルタリングしていました:

export function getTagPosts(tag: string, fields: string[] = []) {
  const posts = slugs
    .map((slug) => getPostBySlug(slug, fields))
    .filter((post) => post.tag && post.tag.includes(tag)) // ← tagフィールドが必要
}

しかし、getStaticPathsでは['slug']しかフィールドを指定していないため、tagフィールドが読み込まれず、フィルタリングが失敗していました。

解決方法

修正は簡単でした。必要なフィールドを明示的に指定するだけです:

// 修正後のコード
export const getStaticPaths: GetStaticPaths = async () => {
  const tags = getAllTags()
  const paths = []
  
  for (const tag of tags) {
    // 修正:tagフィールドも取得する
    const tagPosts = getTagPosts(tag, ['slug', 'tag'])
    const totalPages = Math.ceil(tagPosts.length / POSTS_PER_PAGE)
    
    for (let page = 2; page <= totalPages; page++) {
      paths.push({
        params: { tag, page: page.toString() }
      })
    }
  }
  
  return { paths, fallback: false }
}

結果

修正後のビルドでは正常にページが生成されました:

✓ Generating static pages (276/276)
├ ● /tags/[tag]/[page]
├   ├ /tags/javascript/2
├   ├ /tags/javascript/3
├   ├ /tags/react/2
└   └ [+22 more paths]

学んだ教訓

この問題から得られた教訓:

  1. フィルタリングに使用するフィールドは必須で取得する
  2. APIの依存関係を明確にする
  3. デバッグログで実際の値を確認する

特にマークダウンベースのブログやCMSを使用している場合、フロントマターのフィールド(tags、categories、slugなど)をフィルタリングに使用することが多いので、同様の問題が発生しやすいです。

まとめ

getStaticPathsでデータフィルタリングを行う際は、フィルタリング条件で使用するフィールドも必ず取得するようにしましょう。この小さな見落としが、404エラーの原因になることがあります。

Next.jsでブログサイトを構築している方の参考になれば幸いです。