こんにちは。
個人開発で、Next.jsを用いたブログサイトの詳細ページを作成していた際に表題のようなエラーが発生しました。
その原因と対策方法について備忘録代わりに記載いたします。
発生したエラーとそれを引き起こしたコード
Next.jsで、ブログサイトの詳細ページ用コードとして以下のようなコードを記載していました。
'use cache';
type Params = {
id: string;
}
export default async function page({ params }: { params: Promise<Params> }) {
const { id } = await params;
// 以下はidを取得するテスト。実際は他の値もprops経由で取得する予定だった
return (
<>
<div>
<p>テスト:{id}</p>
</div>
</>
)
}
このコードでnpm run devで[id]付きページを参照したところ、以下のようなエラーが発生しました。
Error: Route "/[id]": Uncached data or
connection()was accessed outside of<Suspense>. This delays the entire page from rendering, resulting in a slow user experience. Learn more: https://nextjs.org/docs/messages/blocking-route
Error: ルート "/[id]":
cookies()、headers()、params、またはsearchParamsなどのランタイムデータが<Suspense>の外でアクセスされました。これによりページ全体のレンダリングが遅延し、ユーザーエクスペリエンスが低下します。
エラー内容の把握・公式ドキュメントの確認
このようなケースではまずLearn moreで記載されている公式ドキュメントを見るのが第一なので、公式ドキュメントを確認します。
原因となるWhy This Error Occurredの箇所を確認します。
※原文は全て英語なためChatGPT Translateで和訳したものを引用として記載いたします。
cacheComponents 機能が有効になっている場合、Next.js は、すべてのユーザーリクエストでアクセスする必要があるデータを await するコンポーネントの周囲に、親 Suspense 境界があることを想定します。この要件の目的は、Next.js がこのデータへのアクセスとレンダリング中に、有用なフォールバックを提供できるようにすることです。
これは通常、親 Suspense 境界なしでコンポーネントが次のいずれかを行った場合に発生します。
・Page または Layout で params を await する、または Page で searchParams を await する
・cookies()、headers()、または connection() を呼び出す
・"use cache" でキャッシュされていないデータを取得する
参照元:https://nextjs.org/docs/messages/blocking-route#why-this-error-occurred
今回のケースだとcacheComponents機能が有効かつ<Suspense>境界がない状態で"use cache"を使っていることが原因のようでした。
対策例
"use cache"はページの一部は静的にキャッシュさせ、別の部分は動的にレンダリングさせるためのものです。
今回実装していたコードはCMSの詳細ページ=そもそも動的にレンダリングさせる必要性が薄いページだったので、「cacheComponents機能およびuse cacheを使わない」方向で対策しました。
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
// cacheComponents: true を削除する
- cacheComponents: true,
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'images.microcms-assets.io'
}
]
}
};
export default nextConfig;
// 'use cache' を削除する
- 'use cache';
type Params = {
id: string;
}
export default async function page({ params }: { params: Promise<Params> }) {
const { id } = await params;
return (
<>
<div>
<p>テスト:{id}</p>
</div>
</>
)
}
上記のようにcacheComponentsの設定項目を削除し、'use cache'も削除することでエラーが発生せずに動くようになりました。
役割的にServer Component=静的ページで問題ない箇所だったのでこれでも問題なく機能しました。
最後に
ここまで読んでいただきありがとうございました。
'use cache'はつい多用したくなりますが、ページやコンポーネントの役割を考慮して使うことが大事であることを学びました。
参考資料