事象
Next.jsのApp Routerを使用して構築したサイトをVercelでデプロイしています。
サイトを公開してしばらくしても検索結果に出てこなかったので、Google Search Consoleを使ってURL 検査をしてみました。
すると以下のように表示され、インデックスに登録されていないことが判明しました。

※今回調べたのは、「Dart Sassへの移行ガイド」の記事のURLです。
そこで、表示されている「インデックス登録をリクエスト」を押し、ライブテストを確認してみましたが、以下のようになりリクエストを送信することができませんでした。

「ページの可用性」の項目で詳細を確認すると、ページの取得に失敗していることがわかりました。
500番台のエラーが発生しているようですが、それ以上の詳細がわからなかったので、次はVercelのログを見てみます。

VercelのプロジェクトのLogsを開くと、リクエストしたURLが500エラーになっていることがわかりました。
しかし、エラーの詳細などはなく、解決には至りませんでした。
そこで、Vercelで[Deployment Details] > [Building]を開き、ビルドログを見てみます。
すると、調べているURLの生成に使っている /posts/[postId] について、ページ全体がクライアント側でのレンダリング(CSR)に切り替わった、というログが出ていました。
原因・修正
ログに記載されているURL(新しいタブで開く)を開くと、ようやく原因がわかりました。
useSearchParamsを使うコンポーネントをSuspenseで囲んでいなかったため、ページ全体がCSR(Client-side Rendering)になっていたようです。
ビルドログを見ると他のページも同様にCSRになっていたので、共通で使用している /src/app/layout.tsx を確認してみました。
ここで使用している Analytics.tsx 内に'use client'とconst searchParams = useSearchParams()があったので、これが影響していたようです。
layout.tsx で、このClient ComponentをReactのSuspenseで囲み、再度デプロイします。
import { Analytics } from "@/components/Analytics";import { Suspense } from "react";export default function RootLayout({ children,}: { children: React.ReactNode;}) { return ( <html lang="ja"> <body> <Suspense fallback={<></>}> <Analytics /> </Suspense> <div>{children}</div> </body> </html> );}Google Search Consoleで再度インデックス登録をリクエストしたところ、問題なくリクエストを送信することができました。

現在のNext.jsでは、useSearchParamsを使うコンポーネントをSuspenseで囲んでいないと、ビルドの時点で「Missing Suspense boundary with useSearchParams」のエラーになります。対処は同じで、useSearchParamsを使うコンポーネントをSuspenseで囲みます。
参考・引用
- Entire page deopted into client-side rendering | Next.js(新しいタブで開く)
- Missing Suspense boundary with useSearchParams | Next.js(新しいタブで開く)
- Functions: useSearchParams | Next.js(新しいタブで開く)
この記事は役に立ちましたか?